标记符号系统
用于符号的 Web 控件
引言
如今,许多比较网站都提供了对产品或服务进行评分的功能。可以使用多种控件来实现此功能。今天我提交的是我开发的:webstarcontrol。
我的程序的最大优势在于你可以在**同一页面上放置多个控件**,并按你想要的方式管理它们。webstarctrl 具有 2 种模式:
- 编辑模式:网站访客可以自行选择评分。
- 阅读模式:网站访客查看平均评分(以星级表示)。他们只是评分的观察者。
这段代码允许你轻松地将一个非常简单的评分系统集成到你的网站中。它很有用,因为它非常容易参数化。
背景
要使用此控件,你需要提供参数:
InternalId
是必需的,并且每个控件必须具有唯一的 ID(类似于 ID 属性)。ImgScrOk
是选中时的图片路径。这是一个必需属性。ImgScrKo
是未选中时的图片路径。这是一个必需属性。NbrStar
是你可以给出的最大评分。这是一个必需属性。IsReadOnly
在只读模式下显示控件(不处理点击事件),当其值为 true 时。这是一个可选属性。InitialValue
在控件初始化时选择一个数字。
Using the Code
要使用此控件,你必须在你的项目中添加三样东西:
CtrlStar
Web 控件类(CtrlStar.cs)。- JavaScript 文件 starhelper.js。(该文件的路径在 CtrlStar.cs 文件的
OnInit
方法中参数化。) - 你想要显示的图片,通过
ImgScrOk
和ImgScrKo
属性参数化。
我在开发此控件时遇到的主要困难是如何能够将一个页面上的所有控件实例分开。JavaScript 文件允许我们动态生成 HTML,并使用内部 ID 的串联来构建不同的 HTML 对象,从而分隔每个控件。IE 及其兄弟浏览器具有不同的 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);
}
星级点击事件由 JavaScript 函数 setStar
处理,该函数调用客户端方法 setCurrentNumber
,该方法触发服务器端 AJAX 回调。
// ##### 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);
}
要使用 AJAX 功能,页面和/或控件,你必须实现 ICallBackEventHandler
接口,该接口定义了 GetCallbackResult()
和 RaiseCallbackEvent()
服务器端方法。你需要在 OnInit
控件方法中将客户端调用“连接”到服务器端。
public class CtrlStar : WebControl, ICallbackEventHandler
{
...
///
/// Init Event
///
///
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]);
}
}
对于 JavaScript 文件 starhelper.js 客户端,你必须提供这些引用方法:
function FunctionCallBack(result, context)
{}
function FunctionCallBackError(result, context)
{}
function setCurrentNumber(pCurrentNumber , pIdDivContainer)
{
var str = pIdDivContainer+";"+pCurrentNumber;
ExecuteCallBack(str,'context');
}
关注点
我学会了如何使用完整的 JavaScript 处理创建一个 ASP.NET Web 控件。我发现了 IE 和其他浏览器之间的根本区别。
谢谢
感谢 Phillipe Pele 在 JavaScript 兼容性方面提供的帮助(IE / FireFox 等...)。