当前位置: 首页 > 图文教程 > 网络编程 > 网页播放器 > FCKeditor 源代码分析附中文注释

网页播放器
超级REAL视频播放器
网页视频播放器程序代码(通用代码)
通用网页播放器
通用媒体播放器(5.5更新)
在线播放器代码大全
符合web标准的媒体播放器代码
网页播放器的参数含义 Windows Media Player 网页播放器 参数含义
自动切换能播放音乐列表 vbs
ASP电影播放器
一款不错的flash Mp3播放器
Window Media Player 播放器
获取音乐文件的播放时间及当前进度
javascript控制realplayer对象使用
内嵌式RealPlayer播放器的参数含义
功能齐全的Real播放器
多首歌曲连续播放之asx播放列表文件
图片自动播放器脚本之家修正
封装的一个播放器wmv
利用JAVASCRIPT控制MEDIA PLAYER的功能实现
来自CSDN的"无限流"分页程序

网页播放器 中的 FCKeditor 源代码分析附中文注释


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2010-01-10   浏览: 511 ::
收藏到网摘: n/a

FCKeditor 源代码分析(一 ) fckeditor.js的中文注释分析 这几天都在研究FCKeditor的源代码 (FCKeditor就是网络中应用比较广泛的网页编辑器) 这里需要感谢nileaderblog的辛苦翻译。
几乎搜遍了Internet,似乎对于fckconfig.js这个文件讲解的很多,但对于fckeditor.js这个FCK的核心类文件的资料几乎为0.
所以,花了整整一天的时间,以挤牙膏的方式,对fckeditor.js这个fck核心类文件作了自己力所能及的注释,供同样学习fck的网友一个参考。
鉴于笔者水平有限,在此,请广大高手指出我的注释中不妥之处,以免误导他人 。谢谢。
建议copy到自己的IDE中查看 或者
注:本文基于FCKeditor2.6.5
更多权威资料,请参见 FCK 官方Developers Guide
复制代码 代码如下:

/**
*
* ***********CopyRight**************
*-------Annotated by nileader-----
*-----Version 1.00 2009-10-18-----
*-----Once copied, marked http://www.nileader.cn
*
* FCKeditor 类 annotated by nileader
* @param {Object} instanceName 编辑器的唯一名称(相当于ID) 是不可省参数,
* width,height,toolbarset,value 都是 可选参数
*/
var FCKeditor = function( instanceName, width, height, toolbarSet, value )
{
//编辑器的基本属性 注意:这些东西优先于FCKConfig.js中的配置
this.InstanceName = instanceName ; //编辑器的唯一名称(相当于ID)(必须有!)
this.Width = width || '100%' ; //宽度 默认是100%
this.Height = height || '200' ; //宽度 默认是200
this.ToolbarSet = toolbarSet || 'Default' ;//工具集名称,默认值是Default
this.Value = value || '' ; //初始化编辑器的HTML代码,默认值为空
//编辑器初始化的时候默认的根路径, 其作用是编写fck中,凡是用到的路径,均从FCKeditor.BasePath目录开始 默认为/Fckeditor/
this.BasePath = FCKeditor.BasePath ;
this.CheckBrowser = true ; //是否在显示编辑器前检查浏览器兼容性,默认为true
this.DisplayErrors = true ; //是否显示提示错误,默为true
this.Config = new Object() ;
// Events
this.OnError = null ; // function( source, errorNumber, errorDescription )自定义的错误处理函数
}
FCKeditor.BasePath = '/fckeditor/' ; // fck默认的根目录
FCKeditor.MinHeight = 200 ; //高和宽的限制
FCKeditor.MinWidth = 750 ;
FCKeditor.prototype.Version = '2.6.5' ; //版本号
FCKeditor.prototype.VersionBuild = '23959' ;
/**
* 调用CreateHtml()来生成编辑器的html代码并在页面上输出编辑器
*/
FCKeditor.prototype.Create = function()
{
//调用createhtml()方法
document.write( this.CreateHtml() ) ;
}
/**
* @return sHtml 用于生成编辑器的html代码
*/
FCKeditor.prototype.CreateHtml = function()
{
// 检查有无InstanceName 如果没有则不生成html代码
if ( !this.InstanceName || this.InstanceName.length == 0 )
{
this._ThrowError( 701, 'You must specify an instance name.' ) ;
return '' ;
}
//函数的返回值
var sHtml = '' ;
/*
* 当用户的浏览器符合预设的几种浏览器时,
* 生成一个id="this.instancename" name="this.instancename"的文本框,事实上的内容储存器
*/
if ( !this.CheckBrowser || this._IsCompatibleBrowser() )
{
//将此时FCK初始值通过转义之后放入这个input
sHtml += '<input type="hidden" id="' + this.InstanceName + '" name="' + this.InstanceName + '" value="' + this._HTMLEncode( this.Value ) + '" style="display:none" style="display:none" />' ;
//生成一个隐藏的INPUT来放置this.config中的内容
sHtml += this._GetConfigHtml() ;
//生成编辑器的iframe的代码
sHtml += this._GetIFrameHtml() ;
}
/**
* 如果用户的浏览器不兼容FCK默认的几种浏览器
* 只能有传统的textarea了
*/
else
{
var sWidth = this.Width.toString().indexOf('%') > 0 ? this.Width : this.Width + 'px' ;
var sHeight = this.Height.toString().indexOf('%') > 0 ? this.Height : this.Height + 'px' ;
sHtml += '<textarea name="' + this.InstanceName +
'" rows="4" cols="40" style="width:' + sWidth +
';height:' + sHeight ;
if ( this.TabIndex )
sHtml += '" tabindex="' + this.TabIndex ;
sHtml += '">' +
this._HTMLEncode( this.Value ) +
'<\/textarea>' ;
}
return sHtml ;
}
/**
* 用编辑器来替换对应的文本框
*/
FCKeditor.prototype.ReplaceTextarea = function()
{
//如果已经有了 id=THIS.INSTANCENAME___Frame 的标签时,直接返回
if ( document.getElementById( this.InstanceName + '___Frame' ) )
return ;
//当用户的浏览器符合预设的几种浏览器时
if ( !this.CheckBrowser || this._IsCompatibleBrowser() )
{
// We must check the elements firstly using the Id and then the name.
//获取id=this.InstanceName的html标签
var oTextarea = document.getElementById( this.InstanceName ) ;
//获取所有name=THIS.instancename的标签
var colElementsByName = document.getElementsByName( this.InstanceName ) ;
var i = 0;
/*
* 考虑到用户html标签的命名不规范,所以进行以下编历判断 笔者指的是用户在textarea标签处用了name=this.instancename
* 在同个页面的其它标签上也用了name=this.instancename
*/
while ( oTextarea || i == 0 )
{
//遍历,直到找到name=this.instancename的textarea标签,并赋给oTextarea
if ( oTextarea && oTextarea.tagName.toLowerCase() == 'textarea' )
break ;
oTextarea = colElementsByName[i++] ;
}
//如果不存在id或者name为this.instancename的标签时,弹出错误框
if ( !oTextarea )
{
alert( 'Error: The TEXTAREA with id or name set to "' + this.InstanceName + '" was not found' ) ;
return ;
}
/*
* 确定存在name=this.instancename的textarea标签后,将编辑器的代码赋给它
*/
oTextarea.style.display = 'none' ;
//如果页面上对这样的textarea标签定义了tab键的顺序,赋给this.TabIndex待用
if ( oTextarea.tabIndex )
this.TabIndex = oTextarea.tabIndex ;
this._InsertHtmlBefore( this._GetConfigHtml(), oTextarea ) ;
this._InsertHtmlBefore( this._GetIFrameHtml(), oTextarea ) ;
}
}

/**
* 在指定的页面标签前面插入html代码
* @param {Object} 待插入的html代码
* @param {Object} 指定的页面标签(对象)
*/
FCKeditor.prototype._InsertHtmlBefore = function( html, element )
{
if ( element.insertAdjacentHTML ) // IE 私有的 insertAdjacentHTML 方法
element.insertAdjacentHTML( 'beforeBegin', html ) ;
else // 非ie浏览器
{
var oRange = document.createRange() ;
oRange.setStartBefore( element ) ;
var oFragment = oRange.createContextualFragment( html );
element.parentNode.insertBefore( oFragment, element ) ;
}
}

/*
* 通过编历this.Config[]来生成一个隐藏域,
* 例如:
* this.Config['nileader']="1104",this.Config['leaderni']="nichao"……
* 那么,sConfig=…… &nileader=1104&leaderni=nichao ……
* 当然,最终,sConfig会被encodeURIComponent函数转换成百分比编码 放入隐藏的INPUT中去
*/
FCKeditor.prototype._GetConfigHtml = function()
{
var sConfig = '' ;
for ( var o in this.Config )
{
if ( sConfig.length > 0 ) sConfig += '&' ;
//encodeURIComponent函数转换成百分比编码
sConfig += encodeURIComponent( o ) + '=' + encodeURIComponent( this.Config[o] ) ;
}
return '<input type="hidden" id="' + this.InstanceName + '___Config" value="' + sConfig + '" style="display:none" style="display:none" />' ;
}
/*
* 生成iframe的html 这里涉及到src的确定
*/
FCKeditor.prototype._GetIFrameHtml = function()
{
var sFile = 'fckeditor.html' ;
//特殊情况 fckedito所在的窗口没有嵌入在浏览器中
try
{
if ( (/fcksource=true/i).test( window.top.location.search ) )
sFile = 'fckeditor.original.html' ;
}
catch (e) { /* 忽略这个异常. 很多时候,fckedito所在的窗口嵌入在浏览器中. */ }
/*
* 这里注意的一点:
* iframe的工作原理: 当iframe处于可编辑状态时,其实编辑的是src所在的页面
* 这里合成一个sLink以放入iframe标签中
*/
//sLink就是这个事实上的页面了,从fck的根目录开始,例如 sLink=/fckeditor/editor/fckeditor.html?InstanceName=nileader&Toolbar=nileadersbar
var sLink = this.BasePath + 'editor/' + sFile + '?InstanceName=' + encodeURIComponent( this.InstanceName ) ;
if (this.ToolbarSet)
sLink += '&Toolbar=' + this.ToolbarSet ;
//生成一个真正的编辑iframer的html代码 当然,放入了src=slink
var html = '<iframe id="' + this.InstanceName +
'___Frame" src="' + sLink +
'" src="' + sLink +
'" width="' + this.Width +
'" height="' + this.Height ;
//如果设定了使用"Tab"键的遍历顺序,则赋给iframe
if ( this.TabIndex )
html += '" tabindex="' + this.TabIndex ;
html += '" frameborder="0" scrolling="no"></iframe>' ;
return html ;
}
/*
* 检测用户的bowser是否是fck的默认
* 这个方法只是fck公司追求oo,无意义
*/
FCKeditor.prototype._IsCompatibleBrowser = function()
{
return FCKeditor_IsCompatibleBrowser() ;
}
/**
* 抛出错误
* @param {Object} errorNumber 错误编号
* @param {Object} errorDescription 错误概述
*/
FCKeditor.prototype._ThrowError = function( errorNumber, errorDescription )
{
this.ErrorNumber = errorNumber ;
this.ErrorDescription = errorDescription ;
//是否显示提示错误,默为true
if ( this.DisplayErrors )
{ //将错误编号和错误概述打印出来
document.write( '<div style="COLOR: #ff0000" style="COLOR: #ff0000">' ) ;
document.write( '[ FCKeditor Error ' + this.ErrorNumber + ': ' + this.ErrorDescription + ' ]' ) ;
document.write( '</div>' ) ;
}
//OnError是否自定义了错误处理函数,若定义了,由其处理
if ( typeof( this.OnError ) == 'function' )
this.OnError( this, errorNumber, errorDescription ) ;
}
/**
* 转义文本
* @param {Object} text 待转义的文本
* @return String text 转义完后的文本
*/
FCKeditor.prototype._HTMLEncode = function( text )
{
if ( typeof( text ) != "string" )
text = text.toString() ;
//将字符串中的所有 & " < > 用对应的转义字符代换
text = text.replace(
/&/g, "&").replace(
/"/g, """).replace(
/</g, "<").replace(
/>/g, ">") ;
return text ;
}
;(function()
{
//把页面上的textarea元素赋给editor变量
var textareaToEditor = function( textarea )
{
var editor = new FCKeditor( textarea.name ) ;
editor.Width = Math.max( textarea.offsetWidth, FCKeditor.MinWidth ) ;
editor.Height = Math.max( textarea.offsetHeight, FCKeditor.MinHeight ) ;
return editor ;
}
/**
* Replace all <textarea> elements available in the document with FCKeditor
* instances.
*
* // Replace all <textarea> elements in the page.
* FCKeditor.ReplaceAllTextareas() ;
*
* // Replace all <textarea class="myClassName"> elements in the page.
* FCKeditor.ReplaceAllTextareas( 'myClassName' ) ;
*
* // Selectively replace <textarea> elements, based on custom assertions.
* FCKeditor.ReplaceAllTextareas( function( textarea, editor )
* {
* // Custom code to evaluate the replace, returning false if it
* // must not be done.
* // It also passes the "editor" parameter, so the developer can
* // customize the instance.
* } ) ;
*/
FCKeditor.ReplaceAllTextareas = function()
{
//获取所有的textarea元素
var textareas = document.getElementsByTagName( 'textarea' ) ;
for ( var i = 0 ; i < textareas.length ; i++ )
{
var editor = null ;
var textarea = textareas[i] ;
var name = textarea.name ;
// The "name" attribute must exist.
if ( !name || name.length == 0 )
continue ;
if ( typeof arguments[0] == 'string' )
{
// The textarea class name could be passed as the function
// parameter.
var classRegex = new RegExp( '(?:^| )' + arguments[0] + '(?:$| )' ) ;
if ( !classRegex.test( textarea.className ) )
continue ;
}
else if ( typeof arguments[0] == 'function' )
{
// An assertion function could be passed as the function parameter.
// It must explicitly return "false" to ignore a specific <textarea>.
editor = textareaToEditor( textarea ) ;
if ( arguments[0]( textarea, editor ) === false )
continue ;
}
if ( !editor )
editor = textareaToEditor( textarea ) ;
editor.ReplaceTextarea() ;
}
}
})() ;
/**
* 检测浏览器的兼容性
* 利用了navigator对象返回的一些信息sAgent,判断浏览器 返回包括 浏览器的码名 浏览器名 浏览器版本 语言 等信息 并小写
* 例如:
* mozilla/4.0 (compatible; msie 6.0; windows nt 5.2; sv1; .net clr 1.1.4322)
*
* 判断IE浏览器的时候,运用了IE4.0之后支持的增加了对条件编译,
* 由于只是IE支持,在W3C标准浏览器中,该属性是不被支持的。因此,适当的利用该特性,判断IE
*/
function FCKeditor_IsCompatibleBrowser()
{
var sAgent = navigator.userAgent.toLowerCase() ;
// 当前浏览器是Internet Explorer 5.5+
//利用条件编译判断IE 在IE中,/*@cc_on!@*/false == !false == true,
//如果是非IE浏览器,则忽略,/*@cc_on!@*/false == false
if ( /*@cc_on!@*/false && sAgent.indexOf("mac") == -1 ) //不是apple mac os
{
var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1] ;
return ( sBrowserVersion >= 5.5 ) ;
}
// Gecko (Opera 9 tries to behave like Gecko at this point).
//检测是否是OPERA 9 浏览器
if ( navigator.product == "Gecko" && navigator.productSub >= 20030210 && !( typeof(opera) == 'object' && opera.postError ) )
return true ;
// Opera 9.50+
if ( window.opera && window.opera.version && parseFloat( window.opera.version() ) >= 9.5 )
return true ;
// Adobe AIR
// Checked before Safari because AIR have the WebKit rich text editor
// features from Safari 3.0.4, but the version reported is 420.
if ( sAgent.indexOf( ' adobeair/' ) != -1 )
return ( sAgent.match( / adobeair\/(\d+)/ )[1] >= 1 ) ; // Build must be at least v1
// Safari 3+
if ( sAgent.indexOf( ' applewebkit/' ) != -1 )
return ( sAgent.match( / applewebkit\/(\d+)/ )[1] >= 522 ) ; // Build must be at least 522 (v3)
return false ;
}