ScrewTurn Wiki各种问题解决方法.

更换编辑器

鉴于ScrewTurn的编辑器很不好使用,我将其替换成了CKEditor.将替换方法记录如下.

第一步:安装CKEditor for ASP.NET

下载地点在http://ckeditor.com/download.由于我之前用的是ScrewTurn的ASP.NET版本,因此需要下载.NET版本

 

解压之后将_Samples/bin/CKEditor.NET.dll拷贝到ScrewTurn/bin文件夹中.并将CKEditor/ckeditor文件夹拷贝入ScrewTurn网站根目录下.

修改Web.config添加如下配置

<system.web>
        <pages>
            <controls>
                <add tagPrefix="CKEditor" assembly="CKEditor.NET" namespace="CKEditor.NET"/>
            </controls>
        </pages>
</system.web>

第二部:修改ScrewTurn代码

 ScrewTurn原有的Editor定义在Editor.ashx中,主要在Edit.aspx, Post.aspx和两个Admin页面中使用.在这里我们只替换掉Edit.aspx中的Editor控件,其他类似.

修改Edit.aspx中的

<st:Editor ID="editor" runat="server" OnSelectedTabChanged="editor_SelectedTabChanged" />

<p>
    <CKEditor:CKEditorControl ID="editor" runat="server" Toolbar="Full"></CKEditor:CKEditorControl>
</p>

其中的Toolbar="Full"表示工具栏中的项目,具体可以参考CKEditor的文档.

然后修改Editor.aspx.cs中所有对于editor的引用.主要是将原editor.content的get和set方法改成用CKEditor的Text属性,由于CKEditor没有Wiki Markup和可见即所得模式的区别,原来的两种模式的更改和载入的代码页可以去掉.

之后重新生成网站就大功告成了.

 

修正TAB无法切换问题

ScrewTurn使用了一个非常老的AJAX库Anthem,这个库的代码写的非常之诡异,导致ScrewTurn中很多使用AJAX的TAB切换无法正常操作.

修复方法如下

在ScrewTurn\References\Lib\Anthem.NET下,有Anthem的源码压缩包,解压之后包含了一个js文件和若干cs文件.js文件中的Anthem_Callback方法会向url?Anthem_CallBack=true Post一个获取数据的XHttpRequest.之后就由UpdatePage方法来更新页面.造成问题的如下一段代码

if (result.controls) {
    for (var controlID in result.controls) {
        var containerID = "Anthem_" + controlID.split("$").join("_") + "__";
        var control = document.getElementById(containerID);
        if (control) {
            control.innerHTML = result.controls[controlID];
            if (result.controls[controlID] == "") {
                control.style.display = "none";
            } else {
                control.style.display = "";
            }
        }
    }
}

这段代码会遍历result中的controls列表,然后生成containerID,之后去修改containerID对应的DOM元素的内容.

当标签无法切换的时候可以根据返回值生成的ID和页面中元素的ID是不对应的.

究其原因,是因为Manager.cs中生成页面id和生成AJAX返回值使用了不同的方法.

public static void WriteBeginControlMarker(HtmlTextWriter writer, string parentTagName, Control control)
{
    writer.Write("<{0} id=\"{1}\">", parentTagName, "Anthem_" + control.ClientID + "__");
    IUpdatableControl updatableControl = control as IUpdatableControl;
    if (updatableControl != null && updatableControl.UpdateAfterCallBack && IsCallBack)
    {
        writer.Write(_beginControlMarker);
        writer.Write(GetUniqueIDWithDollars(control));
        writer.Write("-->");
    }
}

这里可以看到,页面元素中的ID是使用control.ClientID生成的.

而AJAX返回的响应中的生成代码在如下两段

private Hashtable GetControls(string html)
{
    Hashtable controls = new Hashtable();

    // Find the first begin marker.
    int i = html.IndexOf(_beginControlMarker);
    // Keep looping while we've got markers.
    while (i != -1)
    {
        i += _beginControlMarker.Length;
        // Find the end of the begin marker.
        int j = html.IndexOf("-->", i);
        if (j == -1)
        {
            break;
        }
        else
        {
            // The string between i and j should be the ClientID.
            string id = html.Substring(i, j - i);

            // Point past the end of the begin marker.
            i = j + 3;
            string endMarker = _endControlMarker + id + "-->";
            // Find the end marker for the current control.
            j = html.IndexOf(endMarker, i);
            if (j == -1)
            {
                break;
            }
            else
            {
                // The string between i and j is now the HTML.
                string control = html.Substring(i, j - i);
                controls[id] = control;
                // Point past the end of the end marker.
                i = j + endMarker.Length;
            }
        }
        // Find the next begin marker.
        i = html.IndexOf(_beginControlMarker, i);
    }
    return controls;
}
if (_updatePage)
{
    string html = HttpContext.Current.Response.ContentEncoding.GetString(htmlBuffer.GetBuffer());
    viewState = GetViewState(html);
#if V2
    viewStateEncrypted = GetViewStateEncrypted(html);
    eventValidation = GetEventValidation(html);
#endif
    controls = GetControls(html);
    foreach (object o in _targets.Values)
    {
        Control c = o as Control;
        if (c != null && !c.Visible)
        {
            if (c.ID!= null && controls.ContainsKey(c.ID))
                controls[c.ID] = "";
        }
    }

    scripts = GetScripts(html);
}

在GetControls方法中,该库使用了在WriteBeginControlMarker写入的control.ClientID来生成controls表,之后又使用control.ID来生成controls表.

在msdn中,我们可以看到这三者的不同

UniqueID:此属性与 ID 属性不同,因为 UniqueID 属性包含服务器控件的命名容器的标识符。
ClientID: 如果 Web 服务器控件作为 HTML 元素呈现时, HTML 元素的 id 属性设置为 ClientID 属性的值。

 

这样一来,AJAX的返回显然有可能和页面中的元素ID不一致.

如果需要修正这个问题,只需要把这三个ID改成同一个(我使用的是UniqueID),然后重新生成Anthem.dll拷贝入网站的bin目录下就可以了.

posted on 2013-06-20 13:43  triStone  阅读(717)  评论(1编辑  收藏  举报

导航