in

ASP.NET Weblogs

Joe Audette

March 2008 - Posts

  • One Bookmarking Service to Rule Them All and in The Widget Bind Them

    I'm sure those of you out there reading this blog also read a lot of other blogs and have noticed over time the chickletization of blog pages with little icons for all the different bookmarking services like Del.icio.us and Digg, and on and on with the ever growing plethora of other services. I was starting to feel that the mojoPortal blog was a little behind the times in this respect. Then I noticed on TechCrunch, the use of the AddThis.com widget. After looking into the integration I could see that it was relatively low hanging fruit to implement a .NET control that makes it easy to add the AddThis button.

    Use of the .NET control in markup is like this:

    <mp:AddThisButton ID="at1" runat="server"
    AccountId=""
    ButtonImageUrl="~/Data/SiteImages/addthisbookmarkbutton.gif"
    Text="Share This Using Popular Bookmarking Services"
    CustomBrand="mojoPortal"
    CustomLogoUrl="http://www.mojoportal.com/Data/mojoportal_box_dropshadow.png"
    CustomLogoBackgroundColor="e8e8e8"
    CustomOptions=""
    UrlToShare=""
    TitleOfUrlToShare=""
    />

    If you leave the UrlToShare and TitleofUrlToShare blank it automatically uses the current page which makes it easy to add it to the layout.master file of your mojoPortal skin so it appears on every page.

    In the blog we databind those properties to the title and url of the blog post.

    If the account id is not set the control doesn't render.

    Now we can just let AddThis.com keep track of the emerging services and add them for us instead of having to add a new chicklet every time some cool new service appears.

    At the time of this post, this feature is only available from the mojoPortal source code repository, but it will be in the next release coming soon.

    You can see the full source code for the control below, in case you want to use it in your own projects. By inheriting from the Hyperlink the implementation was very easy to do. Just wiring up a little javascript and encapsulating the customizable attributes into properties.

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Globalization;
    using System.Text;
    using System.Web.UI;
    using System.Web.UI.WebControls;


    namespace mojoPortal.Web.Controls
    {
        /// <summary>
        /// Author:                    Joe Audette
        /// Created:                2008-03-27
        /// Last Modified:            2008-03-27
        ///       
        /// The use and distribution terms for this software are covered by the
        /// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
        /// which can be found in the file CPL.TXT at the root of this distribution.
        /// By using this software in any fashion, you are agreeing to be bound by
        /// the terms of this license.
        ///
        /// You must not remove this notice, or any other, from this software.   
        ///
        ///
        /// See http://www.addthis.com
        ///
        ///
        ///
        /// </summary>
        public class AddThisButton : HyperLink
        {
            #region Private Properties

            private string accountId = string.Empty;
            private bool useMouseOverWidget = true;
            private string customLogoUrl = string.Empty;
            private string customLogoBackgroundColor = string.Empty;
            private string customLogoColor = string.Empty;
            private string customBrand = string.Empty;
            private string customOptions = string.Empty;
            private int customOffsetTop = -999;
            private int customOffsetLeft = -999;
            private string buttonImageUrl = "~/Data/SiteImages/addthissharebutton.gif";
            private string protocol = "http";

            private string urlToShare = string.Empty;
            private string titleOfUrlToShare = string.Empty;

            #endregion


            #region Public Properties


            /// <summary>
            /// Your addthis.com username.
            /// If this is not set the control will not render.
            /// </summary>
            public string AccountId
            {
                get { return accountId; }
                set { accountId = value; }
            }

            /// <summary>
            /// if true will show widget in the page
            /// </summary>
            public bool UseMouseOverWidget
            {
                get { return useMouseOverWidget; }
                set { useMouseOverWidget = value; }
            }

            /// <summary>
            /// The logo to display on the popup window (about 200x50 pixels).
            /// The popup window is show when the user selects the 'More' choice
            /// </summary>
            public string CustomLogoUrl
            {
                get { return customLogoUrl; }
                set { customLogoUrl = value; }
            }

            /// <summary>
            /// The color to use as a background around the logo in the popup
            /// </summary>
            public string CustomLogoBackgroundColor
            {
                get { return customLogoBackgroundColor; }
                set { customLogoBackgroundColor = value; }
            }


            /// <summary>
            /// The color to use for the text next to the logo in the popup
            /// </summary>
            public string CustomLogoColor
            {
                get { return customLogoColor; }
                set { customLogoColor = value; }
            }


            /// <summary>
            /// The brand name to display in the drop-down (top right)
            /// </summary>
            public string CustomBrand
            {
                get { return customBrand; }
                set { customBrand = value; }
            }


            /// <summary>
            /// A comma-separated ordered list of options to include in the drop-down
            /// Example: addthis_options = 'favorites, email, digg, delicious, more';
            /// Currently supported options:
            /// delicious, digg, email, favorites, facebook, fark, furl, google, live, myweb, myspace,
            /// newsvine, reddit, slashdot, stumbleupon, technorati, twitter, more
            /// (the default is currently 'favorites, digg, delicious, google, myspace, facebook,
            /// reddit, newsvine,
            /// live, more', in that order).
            /// </summary>
            public string CustomOptions
            {
                get { return customOptions; }
                set { customOptions = value; }
            }

            /// <summary>
            /// Vertical offset for the drop-down window widget (in pixels)
            /// thiscontrol defaults to -999 which means unsepcified
            /// this will result in the defaults from addthis.com
            /// not sure what the defsault is
            /// </summary>
            public int CustomOffsetTop
            {
                get { return customOffsetTop; }
                set { customOffsetTop = value; }
            }

            /// <summary>
            /// Horizontal offset for the drop-down window widget (in pixels)
            /// thiscontrol defaults to -999 which means unsepcified
            /// this will result in the defaults from addthis.com
            /// not sure what the defsault is
            /// </summary>
            public int CustomOffsetLeft
            {
                get { return customOffsetLeft; }
                set { customOffsetLeft = value; }
            }

            public string ButtonImageUrl
            {
                get { return buttonImageUrl; }
                set { buttonImageUrl = value; }
            }

            public string UrlToShare
            {
                get { return urlToShare; }
                set { urlToShare = value; }
            }

            public string TitleOfUrlToShare
            {
                get { return titleOfUrlToShare; }
                set { titleOfUrlToShare = value; }
            }


            #endregion

            protected override void OnPreRender(EventArgs e)
            {
                base.OnPreRender(e);

                if (accountId.Length == 0)
                {
                    this.Visible = false;
                    return;
                }

                if (Page.Request.IsSecureConnection)
                    protocol = "https";

                SetupScripts();

                this.ImageUrl = Page.ResolveUrl(buttonImageUrl);
                this.NavigateUrl = "http://www.addthis.com/bookmark.php";

                if (useMouseOverWidget)
                    SetupWidget();
                else
                    SetupNormalLink();

            }

            private void SetupNormalLink()
            {
                StringBuilder onClickAttribute = new StringBuilder();

                if (urlToShare.Length > 0)
                {
                    onClickAttribute.Append("addthis_url = '" + urlToShare + "'; ");
                }
                else
                {
                    onClickAttribute.Append("addthis_url = location.href; ");
                }

                if (titleOfUrlToShare.Length > 0)
                {
                    onClickAttribute.Append("addthis_title ='" + titleOfUrlToShare + "'; ");
                }
                else
                {
                    onClickAttribute.Append("addthis_title = document.title; ");

                }

                onClickAttribute.Append("return addthis_click(this); ");

                this.Attributes.Add("onclick", onClickAttribute.ToString());

                //this.Attributes.Add("onclick", "return addthis_click(this); ");

            }

            private void SetupWidget()
            {
                StringBuilder mouseOverAttribute = new StringBuilder();

                mouseOverAttribute.Append("return addthis_open(this, '',");

                if (urlToShare.Length > 0)
                {
                    mouseOverAttribute.Append("'" + urlToShare + "', ");
                }
                else
                {
                    mouseOverAttribute.Append("'[URL]', ");
                }

                if (titleOfUrlToShare.Length > 0)
                {
                    mouseOverAttribute.Append("'" + titleOfUrlToShare + "' ");
                }
                else
                {
                    mouseOverAttribute.Append("'[TITLE]' ");

                }

                mouseOverAttribute.Append("); ");

               
                this.Attributes.Add("onmouseover", mouseOverAttribute.ToString());

                this.Attributes.Add("onmouseout", "addthis_close()");

            }

            private void SetupScripts()
            {
                StringBuilder script = new StringBuilder();
                script.Append("<script language=\"javascript\" type=\"text/javascript\"> ");
                script.Append("\n<!-- \n");

                script.Append("var addthis_pub = '" + accountId + "';");

                if(customLogoUrl.Length > 0)
                    script.Append("var addthis_logo = '" + customLogoUrl + "';");

                if (customLogoBackgroundColor.Length > 0)
                    script.Append("var addthis_logo_background = '" + customLogoBackgroundColor + "';");

                if (customLogoColor.Length > 0)
                    script.Append("var addthis_logo_color = '" + customLogoColor + "';");

                if (customBrand.Length > 0)
                    script.Append("var addthis_brand = '" + customBrand + "';");

                if (customOptions.Length > 0)
                    script.Append("var addthis_options = '" + customOptions + "';");

                if (customOffsetTop != -999)
                    script.Append("var addthis_offset_top = " + customOffsetTop.ToString(CultureInfo.InvariantCulture) + ";");

                if (customOffsetLeft != -999)
                    script.Append("var addthis_offset_left = " + customOffsetLeft.ToString(CultureInfo.InvariantCulture) + ";");


                script.Append("\n//--> ");
                script.Append(" </script>");


                Page.ClientScript.RegisterClientScriptBlock(
                    typeof(AddThisButton),
                    "addthisbutton",
                    script.ToString());

                if(useMouseOverWidget)
                    Page.ClientScript.RegisterStartupScript(
                        typeof(AddThisButton),
                        "addthisbuttonsetup", "\n<script type=\"text/javascript\" src=\""
                        + protocol + "://s7.addthis.com/js/152/addthis_widget.js"
                        + "\" ></script>");
                else
                    Page.ClientScript.RegisterStartupScript(
                        typeof(AddThisButton),
                        "addthisbuttonsetup", "\n<script type=\"text/javascript\" src=\""
                        + protocol + "://s9.addthis.com/js/widget.php?v=10"
                        + "\" ></script>");

            }
           




        }
    }
     

    Posted Mar 28 2008, 02:27 PM by joeaudette with 2 comment(s)
    Filed under: ,
  • Yahoo Media Player - Sweet and Easy

     cross posted from www.joeaudette.com

    I first read about Yahoo Media Player a month or so back and I bookmarked it with the intention of using it on my site. I don't know why I waited, I must have just been too busy or absorbed in other things I was working on. I mean its a 2 minute job to integrate it, you just add a script to your page or in my case to the layout.master (ASP.NET Master Page) file in my mojoPortal skin like this:

    <script type="text/javascript" src="http://mediaplayer.yahoo.com/js"></script>

    and thats all there is to it. Any page that has links to mp3 files now autmatically have little play buttons next to them.

    Yahoo Media Player automatically adds play buttons

    Click the image above or visit this link to see it on my site: http://www.joeaudette.com/therealitysaladband.aspx

    If you click a play button the player comes up at the bottom of the screen and has a playlist of all the mp3s linked on the page.

     

     

    Pretty cool and so easy a caveman could do it.

     

    Posted Mar 09 2008, 08:36 AM by joeaudette with no comments
    Filed under: ,
  • SubSonic - All Your Databases Are Belong To Us

     Cross posted from mojoPortal.com

    In the week prior to my vacation I had started working with SubSonic to see if it could be useful in mojoPortal since it has support for a number of databases, I figured it could reduce the work of supporting all these different dbs.

    SubSonic is basically a toolkit for interogating databases for their schema and has the ability to generate db specific sql statements for common tasks. It also has a code generation feature so it can generate .NET classes based on database tables. It can be used as an OR mapper, that is, you could use the generated classes as your business objects, you could either inherit from them or use partial classes to bolt on custom functionality on top of what was generated by SubSonic. But for people like me who just never bought into the whole OR mapper thing, the generated classes can just be thought of as data objects that abstract the database table. It can return standard data in the form of IDataReader which is what the mojoPortal business objects like to consume and allows using SubSonic without having any particular dependency on SubSonic in my business classes.

    It comes with providers for MS SQL, Oracle, MySql and SQLite and there were some other partially complete providers that I found in the wild. So my plan was, for proof of concept, to take a simple feature like the links module and try to re-implement it for all the dbs by using SubSonic. The short story is, yes I got it working for all 5 of the currently supported databases in mojoPortal. I re-implemented a new SQLite provider using Mono.Data.Sqlite which I already knew works both on Windows and on Linux/Mono. I found a postgresql provider here (thanks to Justin Greene and Maurício Machado) that was usable with a little bit of work. I also found a starter implementation for Firebird Sql (thanks to  Ricardo García) that I was able to complete and get working.

    I've since gone on to implement the data layer for the WebStore feature for MySql, mostly using SubSonic. And the things that did use SubSonic are completely re-usable for the other data layers so the bulk of the work is already done for implementing the web store for postgre sql and Firebird.

    SubSonic also comes with a thing called the scaffold page which is basically a web page that allows managing data in all of the tables in your database. Just drop it in and it works. I've modified the one in mojoPortal a little for various little issues I encountered and also to add security checks to control access to the page.

    Since the code templates used by SubSonic are basically .aspx pages, I got the idea of making a browser based gui for code generation. I implemented that today and got the initial proof of concept done in about 4 hours of playing around. So at the moment its kind of like a poor man's Codesmith in the browser.

    At any rate, I made a quick tutorial video about use of SubSonic in mojoPortal, sort of a developers introduction to it. Its pretty cool stuff so I hope you'll have a look.

    An Intoduction to SubSonic as Used in mojoPortal

     

More Posts