imathis/octopress — Issue #466: Liquid Exception: Variable '{{ {0}' was not properly terminated with regexp: /\}\}/  in
Author: huobazi
Created: 2012-03-04 04:01:07+00:00
State: open

Liquid Exception: Variable '{{document.forms[0].__SCROLLPOS_TOP.value = {0}' was not properly terminated with regexp: /\}\}/ in 2004-09-20-scrollpage.markdown
Liquid Exception: Variable '{{ {0}' was not properly terminated with regexp: /\}\}/ in 2007-08-05-advertisementlazyloadingcontrol.markdown
Liquid Exception: Variable '{{ {0}' was not properly terminated with regexp: /\}\}/ in atom.xml
Liquid Exception: Variable '{{ {0}' was not properly terminated with regexp: /\}\}/ in atom.xml

the mk file:

---
layout: post
title: Scroll Page 表单提交后页面重新滚回原来滚动条所在位置
comments: true
date: 2004-09-20 13:55
categories:
- ASP.NET
- 前端开发
- Asp.net
---

作者scottwater
原文地址：http://scottwater.com/articles/ScrollPage
感谢scottwater先生！
我做了一点修改，使其支持横向滚动条位置的记忆

```
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;

namespace ShangGu.XaTaxi.Components
{
///

/// Summary description for ScrollPage.
///

public class ScrollPage : System.Web.UI.Page
{
public ScrollPage()
{

}

private bool _useScrollPersistence = true;
///

/// There could be PostBack senarios where we do not want to remember the scroll position. Set this property to false
/// if you would like the page to forget the current scroll position
///

public bool UseScrollPersistence
{
get {return this._useScrollPersistence;}
set {this._useScrollPersistence = value;}
}

private string _bodyID;
///

/// Some pages might already have the ID attribute set for the body tag. Setting this property will not render the ID or change
/// the existing value. It will simply update the javascript written out to the browser.
///

public string BodyID
{
get {return this._bodyID;}
set {this._bodyID = value;}
}

//Last chance. Do we want to maintain the current scroll position
protected override void OnPreRender(EventArgs e)
{
if(UseScrollPersistence)
{
RetainScrollPosition();
}
base.OnPreRender (e);
}

protected override void Render(HtmlTextWriter writer)
{
//No need processing the HTML if the user does not want to maintain scroll position or already has
//set the body ID value
if(UseScrollPersistence)
{
TextWriter tempWriter = new StringWriter();
base.Render(new HtmlTextWriter(tempWriter));
if(BodyID == null)
{
writer.Write(Regex.Replace(tempWriter.ToString(),"";

//Write out javascript and hidden field
private void RetainScrollPosition()
{
RegisterHiddenField("__SCROLLPOS_TOP", "0");
RegisterHiddenField("__SCROLLPOS_LEFT", "0");
string __bodyID = BodyID == null ? "thebody" : BodyID;
RegisterStartupScript("saveScroll", string.Format(saveScrollPosition,__bodyID));

if(Page.IsPostBack)
{
RegisterStartupScript("setScroll", string.Format(setScrollPosition,__bodyID, Request.Form["__SCROLLPOS_TOP"],Request.Form["__SCROLLPOS_LEFT"]));
}
}
}
}
```

---
layout: post
title: 自定义控件实现广告内容后期加载，以及NamingContainer层次的应用
comments: true
date: 2007-08-05 13:49
categories:
- ASP.NET
- Asp.net
- 自定义控件
- NamingContainer
---

自定义控件：广告内容后期加载。以及NamingContainer层次的应用
网站上的广告内容可能会因加载过慢而导致整个网页加载过慢
我们可以考虑将广告内全部放在网页最底部，等整个页面加载完毕後
再采用javascript使其显示，考虑给控件一个TargetContainerID标识
控件广告内容将要被显示的容器ID，然后从控件自己所处的 开始向上查找该ID
所指定的控件，(我们只向上找而没有向下找，并且没有处理某层次的
子NamingContainer,所以不一定能够找到，这里没有考虑从Page对象向下递归查找
主要考虑为了提高性能),如果没有找到，则考虑给用户一个事件让用户自己处理TargetContainer

下面的自定义控件对此实现了封装:

```
//------------------------------------------------------------------------------
//
// Copyright (c) www.AspxBoy.com All rights reserved.
//
//------------------------------------------------------------------------------
namespace HBZ.Ads.Controls
{
using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using HBZ.Ads;
using System.Collections.Generic;
using System.Text;
[Designer( typeof( HBZ.Ads.Controls.AdRotatorDesigner ) )]
public class AdRotator : WebControl
{
private Dictionary findControlHelperCacheList = new Dictionary( );
private readonly string scriptFormat = " var {0}_target = document.getElementById(\"{0}\"); var {1}_base = document.getElementById(\"{1}\"); if ({0}_target) {{ {0}_target.innerHTML = {1}_base.innerHTML; {1}_base.innerHTML = \"\"; }}";
private static readonly object eventObj = new object( );
public event FindTargetContainerEventHandler FindTargetContainer
{
add
{
Events.AddHandler( eventObj , value );
}
remove
{
Events.RemoveHandler( eventObj , value );
}
}
public AdRotator( )
: base( HtmlTextWriterTag.Span )
{
}
[TypeConverter( typeof( ValidatedControlConverter ) )]
[DefaultValue( "" ) , Category( "Data" ) , Description( "广告位后期加载后显示的位置的控件ID" )]
[IDReferenceProperty]
public string TargetContainerID
{
get
{
return (string)this.ViewState[ "TargetContainerID" ] ?? string.Empty;
}
set
{
this.ViewState[ "TargetContainerID" ] = value;
}
}
[Bindable( true ) , Category( "Data" ) , DefaultValue( "" ) , Description( "广告位的默认内容" )]
public string DefaultContent
{
get
{
return (string)this.ViewState[ "DefaultContent" ] ?? "广告位招租";
}
set
{
this.ViewState[ "DefaultContent" ] = value;
}
}
protected override void OnPreRender( EventArgs e )
{
base.OnPreRender( e );
if ( !string.IsNullOrEmpty( TargetContainerID ) )
{
this.Style.Add( HtmlTextWriterStyle.Display , "none" );
ClientScriptManager cs = Page.ClientScript;
if ( !cs.IsStartupScriptRegistered( this.ClientID ) )
{
cs.RegisterStartupScript( this.GetType( ) , this.ClientID , GetLazyLoadingScript( ) , true );
}
}
}
protected virtual string GetLazyLoadingScript( )
{
Control target = FindControlHelper( TargetContainerID );
if ( target == null )
{
throw new TargetContainerNotFoundException( );
}
StringBuilder sb = new StringBuilder( );
sb.AppendFormat( scriptFormat , target.ClientID , this.ClientID );
return sb.ToString( );
}
protected virtual void RenderAdvertisement( Advertisement ad , HtmlTextWriter writer )
{
// 广告内容
}
protected override void RenderContents( HtmlTextWriter writer )
{
// call RenderAdvertisement method
}
protected Control FindControlHelper( string id )
{
Control c = null;
if ( findControlHelperCacheList.ContainsKey( id ) )
{
c = findControlHelperCacheList[ id ];
}
else
{
c = base.FindControl( id ); // 注意：我们从自己开始向上沿NamingContainer层次查找
Control nc = NamingContainer;
while ( ( null == c ) && ( null != nc ) )
{
c = nc.FindControl( id );
nc = nc.NamingContainer;
}
if ( null == c )
{
// 因为我们是从自己开始向上沿NamingContainer层次查找，而没有向下找，
// 并且没有找每一层NamingContainer内的其他NamingContainer,
// 所以这种查找有可能出现没有找到id对应的控件
// 当没此时有找到时，激发FindTargetContainer事件交给用户自己设定Target Container Control
FindTargetContainerEventArgs args = new FindTargetContainerEventArgs( id );
OnFindTargetContainer( args );
c = args.Control;
}
if ( null != c )
{
findControlHelperCacheList[ id ] = c;
}
}
return c;
}
protected virtual void OnFindTargetContainer( FindTargetContainerEventArgs e )
{
FindTargetContainerEventHandler hander = Events[ eventObj ] as FindTargetContainerEventHandler;
if ( hander != null )
{
hander( this , e );
}
}
}
public delegate void FindTargetContainerEventHandler( object src , FindTargetContainerEventArgs e );
public class FindTargetContainerEventArgs : EventArgs
{
private string controlID;
private Control control;
public FindTargetContainerEventArgs( string controlId )
{
controlID = controlId;
}
public string ControlID
{
get
{
return controlID;
}
}
public Control Control
{
get
{
return control;
}
set
{
control = value;
}
}
}
public class TargetContainerNotFoundException : Exception
{
string exceptionMessage = string.Empty;
public TargetContainerNotFoundException( )
: this( "TargetContainerID所指定的控件没有找到！您或许应该处理一下FindTargetContainer事件" )
{
}
public TargetContainerNotFoundException( string message )
: base( message )
{
this.exceptionMessage = message;
}
public override string Message
{
get
{
if ( exceptionMessage != null )
{
return exceptionMessage;
}
return base.Message;
}
}
}
}
```