Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Mark Notation System

2.36/5 (5 votes)
21 Feb 2008CPOL2 min read 1   106  
A webcontrol for the notation

Introduction

Sample Image

Today, many comparator sites give the possibility to assign a mark to a product or a service. Several controls can be used to do this. Today I submit mine: the webstarcontrol.

The big advantage to my program is that you can put several controls on the same page and you manage them as you want. The webstarctrl has 2 modes:

  • Edit mode: The website visitor who assigns the mark can select his/her own mark.
  • Read mode: The website visitor watches the average mark (represented by stars). He is just an observer of the mark.
    This code allows you to easily integrate a very simple mark system on your website. It's useful because it is very simple to parametrize.

Background

To use this control, you need to provide parameters:

  • InternalId is required and each control must have a unique ID (like ID property)
  • ImgScrOk is the path of the picture when selected. It's a required property
  • ImgScrKo is the path of the picture when not selected. It's a required property
  • NbrStar is the maximal mark you can give. It's a required property
  • IsReadOnly displays the control in consultation (without handling an event click) when it takes the true value. It's an optional property.
  • InitialValue select a number at the initialisation of the control.

Using the Code

To use this control, you must add three things on your project:

  • the CtrlStar webcontrol class (CtrlStar.cs).
  • the JavaScript file starhelper.js. (the path of this file is parametrized on the OnInit method of the CtrlStar.cs file.
  • the pictures you want to display parametrized on ImgScrOk and ImgScrKo properties.

The main difficulty I encountered in developing this control was to be able to separate all the instances of the controls in one page. The JavaScript file allows us to dynamically generate HTML, and it builds its different HTML Objects with concatenation of the internalId to separate each control. IE and its other brothers don't have the same JavaScript implementation, and you must write different code for each brother.

JavaScript
function BuildStars(pStarNumber , pIdDivContainer , pImgScrOk , pImgScrKo, pReadOnly ,
    pInitValue)
    {
       
       if(pImgScrKo == '')
        {
            alert('You must specify the image path KO');
            return ;
        }
       if(pImgScrOk == '')
        {
            alert('You must specify the image path OK');
            return ;
        }
        if(pStarNumber == '')
        {
            alert('You must specify stars number');
            return ;
        }
        if(pIdDivContainer =='')
        {
            alert('You must specify the div Id Container');
            return ;
        }
        
        if(! document.getElementById(pIdDivContainer))
        {
            alert('Not found div Id in document');
            return;
        }
        var i;
        var idContainer = document.getElementById(pIdDivContainer);
        
        
        var table = document.createElement('table');
        table.setAttribute('id', 'table'+pIdDivContainer);
        table.setAttribute('border','0');
        idContainer.appendChild(table);
        
        // tbody is required for IE and understood by Mozilla
        var tbody = document.createElement('TBODY');
        table.appendChild(tbody);
        var tr = document.createElement('tr');
        tr.setAttribute('id',"tr"+pIdDivContainer);
        tbody.appendChild(tr);
        
     
        for( i = 0 ; i < pStarNumber ; i++)
        {
        
            var td = document.createElement('td');
            td.setAttribute('id', 'td'+pIdDivContainer+i);
            
            var hlink = document.createElement('a');
            hlink.setAttribute('id', 'a'+pIdDivContainer+i);
            var nb = i+1;
            
            //case IE
            if( IsIE()  )
            {
        
                  hlink.attachEvent("onclick", function(e){
                  
                        
                        //step 1 : find link click event source
                        var varIdValue;
                        var Obj;
                        
                        if( !e) e = event;
                        
                        if( e.target)
                        {
                            Obj= e.target;
                        }
                        else
                        {
                          Obj = e.srcElement;
                          while(Obj.parentNode)
                          {
                            Obj= Obj.parentNode;
                            //-- Si c'est un lien
                            if( Obj.tagName == "A") 
                            {   
                               varIdValue = Obj.id;
                            }
                          }
                        }
                        
                        //a + length of pIdDivContainer
                        var nbr = 1 + pIdDivContainer.length;
                        var idValue = varIdValue.substr(nbr , varIdValue.length - nbr);
                        idValue ++;
                               
                        //step 2 : find link click event source     
                        setStar(idValue , pStarNumber , pIdDivContainer,pImgScrOk,
                            pImgScrKo);
                        

                    }
                  )

            } 
            else //FireFox , safari ,netscape
            {
                hlink.setAttribute("onclick","setStar("+nb+","+pStarNumber+",
                    '"+pIdDivContainer+"','"+pImgScrOk+"','"+pImgScrKo+"')");
            }
            
            
            var imgo = new Image();
            imgo.id='img'+pIdDivContainer+i;
            // Set init Value
            if(pInitValue > 0)
            {
                if(nb <= pInitValue)
                    {imgo.src=pImgScrOk;}
                else
                    {imgo.src=pImgScrKo;}
            }
            else
                {imgo.src=pImgScrKo;}
            
            imgo.border='0';
             
            
            tr.appendChild(td);
            
             //Normal Mode
             if(pReadOnly == '0')
             {
                td.appendChild(hlink);
                hlink.appendChild(imgo);
             }
             //ReadOnlyMode Mode
             else
             {
                td.appendChild(imgo);
             }
            
        }
        
        var currentSelected = document.createElement('input');
        currentSelected.id='hiddenVal'+pIdDivContainer;
        currentSelected.setAttribute('type','hidden');
        
        if(pInitValue > 0)
        {
            currentSelected.setAttribute('value',pInitValue);
        }
        else
            {currentSelected.setAttribute('value','0');}
        
        idContainer.appendChild(currentSelected);
        
    }

The star click event is handling on the JavaScript function setStar and this function call the method client setCurrentNumber whose trigger is a Server side AJAX CallBack.

JavaScript
// ##### star click eventhandler############
 function setStar(pNumber,totalStar,IdDivContainer,pImgScrOk,pImgScrKo)
 {
     var i;

     for(i=0 ;  i < pNumber ; i++)
     {

         if(document.getElementById('img'+IdDivContainer+i))
         {
             var curImg = document.getElementById('img'+IdDivContainer+i);
             curImg.src = pImgScrOk;
         }
     }
     for(i=pNumber ;  i <= totalStar ; i++)
     {
         if(document.getElementById('img'+IdDivContainer+i))
         {
             var curImg = document.getElementById('img'+IdDivContainer+i);
             curImg.src = pImgScrKo;
         }
     }

     divContainer = document.getElementById(IdDivContainer);
     oldNode = document.getElementById('hiddenVal'+IdDivContainer);

     var currentSelected = document.createElement('input');
     currentSelected.id='hiddenVal'+IdDivContainer;
     currentSelected.setAttribute('type','hidden');
     currentSelected.setAttribute('value',pNumber);

     divContainer.replaceChild(currentSelected,oldNode);

     setCurrentNumber(pNumber,IdDivContainer);


 }

To use AJAX Functionality, Pages and/or Controls, you must implement the ICallBackEventHandler interface defining methods GetCallbackResult() and RaiseCallbackEvent() Server side. You need to "connect" the Client side call to the server side on the OnInit Control method.

C#
 public class CtrlStar : WebControl, ICallbackEventHandler
    {
    ...
    
       /// <summary />
        /// Init Event
        /// </summary />
        /// <param name=""e"" /></param />
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            StreamReader fp = File.OpenText(Page.Server.MapPath("~/") + "\\js\\" +
                "starhelper.js");
            string js = fp.ReadToEnd();
            fp.Close();


            
            Page.ClientScript.RegisterClientScriptBlock(
               this.GetType(),
               "scrManager",
               js.ToString(),
               true);


           
            string ReferenceVersFonctionClienteInitiatriceDuCallBack = 

            Page.ClientScript.GetCallbackEventReference(
            
this, 
            
"arg", 
            
"FunctionCallBack", 
            
"context", 
            
"FunctionCallBackError", 
            
false);
            string ScriptFonctionCliente = 

            "function ExecuteCallBack(arg,context){" +
                ReferenceVersFonctionClienteInitiatriceDuCallBack + ";}";
            Page.ClientScript.RegisterClientScriptBlock(
                this.GetType(),
                "callback",
                ScriptFonctionCliente,
                true);


            HtmlGenericControl h = new HtmlGenericControl();
            h.TagName = "div";
            h.ID = InternalId;
            this.Controls.Add(h);


        }
    
        public string GetCallbackResult()
        {

            return "";

        }
  
        public void RaiseCallbackEvent(string eventArgument)
        {
            string[] tks = eventArgument.Split(';');
            setNbrClickedStar(tks[0], tks[1]);

        }
    
    }

For the client side on the JavaScript starhelper.js file, you must provide these reference methods:

JavaScript
function FunctionCallBack(result, context)
{}

function FunctionCallBackError(result, context)
{}

function setCurrentNumber(pCurrentNumber , pIdDivContainer)
{
    var str = pIdDivContainer+";"+pCurrentNumber;
    ExecuteCallBack(str,'context');
}

Points of Interest

I have learned how to create an ASP.NET Web control with a complete JavaScript treatment. I discovered the fundamental differences between IE and others browsers.

Thanks

Thanks to Phillipe Pele for his JavaScript compatibility help (IE / FireFox etc...)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)