dojo/text!._掌握Dojo Rich Text编辑器

dojo/text!.

Dojo Rich Text编辑器Dijit.Editor旨在使外观和工作像文字处理程序一样。 它具有工具栏,HTML输出和支持新命令,新按钮和其他功能的插件体系结构。 而且,您不必担心浏览器不兼容。 该编辑器支持多种浏览器,包括Internet Explorer(IE)6/7/8,Firefox3,Chrome和Safari。

在本文中,了解Dojo富文本编辑器的基础知识以及如何使用Dojo提供的插件来提高性能。 您还将创建自己的插件,并学习如何扩展编辑器工具栏。

Dojo Rich Text编辑器

图1显示了经典的Dojo Rich Text Editor。 它的工具栏包含几个有用的命令,例如剪切,复制和粘贴。 您可以以WYSIWYG格式编辑内容。

图1. Dojo Rich Text编辑器
经典的Dojo Rich Text编辑器的屏幕截图

使用编辑器非常简单。 第一步是要求进入您使用编辑器的页面。 在进行所有dojo.require调用的位置(通常是head脚本标签)执行此操作。 您还需要导入CSS文件以选择主题,例如Claro。 确保将body元素CSS类设置为claro ,如清单1所示。

清单1.导入编辑器类定义
<html>
<head>
	<title>Dojo Rich Text Editor</title>
	<style type="text/css">
		@import "../../../dijit/themes/claro/claro.css";
	</style>
	<script type="text/javascript">
		dojo.require("dijit.Editor");
	</script>
</head>
<body class="claro">

</body>
</html>

创建编辑器有两种方法:以编程方式或以声明方式。 两种方法是相同的。 清单2显示了如何以声明方式创建编辑器。

清单2.以声明方式创建编辑器
<div dojoType="dijit.Editor" id="editor1">
    <p>
        This is the content of the editor.
    </p>
</div>

如果浏览创建的编辑器的DOM树,则会发现该编辑器由两部分组成:工具栏和iframe区域。 iframe文档的designMode属性设置为on ,它使您可以直接编辑iframe的内容。 这是编辑器的动力。

启用设计模式后,浏览器使您可以通过调用内置命令来修改内容。 例如,您可以通过在Firefox中调用命令execCommand('bold',false, null)来将所选文本设置为粗体。 每个浏览器中的内置命令都不同。 幸运的是,编辑器可以进行标准化,因此您可以调用编辑器提供的统一API来修改内容。

要使用Dojo Rich Text Editor,请单击工具栏上的按钮图标以触发事件(例如,单击),如图2所示。事件由编辑器或其插件捕获。 通过调用内置命令或直接修改DOM节点,可以更改iframe文档的DOM树。

图2.处理编辑请求的工作流程
显示单击图标,然后单击由编辑器捕获的事件,并转到编辑区域(iframe)

外挂程式

通过Dojo Rich Text Editor的可插入体系结构,您可以通过在编辑器中实现和注册插件来扩展功能。 插件是为编辑器添加功能或更改编辑器行为的工具。 Dojo包括几个编辑器插件,您也可以编写自己的插件。

默认情况下会启用某些插件,例如“撤消”,“重做”,“剪切”和“复制”。 大多数插件都有一个关联的工具栏按钮,例如FindReplace插件。 某些插件(例如EnterKeyHandling)会在不更改工具栏的情况下影响编辑器的行为。 编辑器将按以下方式加载和初始化插件。

  1. 导入必要CSS文件。

    某些插件可能具有与之关联CSS文件。 CSS文件定义了插件的UI布局,因此您需要先将CSS文件导入文档中。

  2. extraPlugins列表中声明该插件。

    应该在extraPlugins列表中声明该插件,以便编辑器可以根据该声明创建插件实例,如清单3所示。

    清单3.声明插件
    <div dojoType="dijit.Editor" id="editor1" extraPlugins="['FindReplace']">
        <p>
            This is the content of the editor.
        </p>
    </div>

    清单3中的示例声明了一个名为FindReplace的插件。

  3. 将声明的插件混入完整的插件列表。

    编辑器会将声明的插件与默认插件混合到完整的插件列表中。 在此阶段,编辑器将保存一个插件名称列表。 实际的插件将在以下步骤中创建。

  4. 创建编辑器的工具栏。

    编辑器仅创建dijit.Toolbar的实例,并将其附加到其DOM节点的子节点,如清单4所示。

    清单4.创建编辑器的工具栏
    if(!this.toolbar){
    	// if you haven't been assigned a toolbar, create one
    	this.toolbar = new dijit.Toolbar({
    		dir: this.dir,
    		lang: this.lang
    	});
    	this.header.appendChild(this.toolbar.domNode);
    }
  5. 根据列表创建插件实例。

    所有的魔术都在这里发生。 编辑器枚举插件名称列表,并一一调用这些名称上的addPlugin 。 在addPlugin方法中,将创建插件,并setToolbar它们的setEditorsetToolbar方法以初始化其上下文。

    清单5.创建插件实例
    postCreate: function(){
    	...
    	// Create the plug-in one by one
    	dojo.forEach(this.plugins, this.addPlugin, this);
    	...
    }
    addPlugin: function(/*String||Object*/plugin, /*Integer?*/index){
    	...
    	// Get the plug-in instance that is referenced by paremeter o.plugin.
    	var o={"args":args,"plugin":null,"editor":this};
    	dojo.publish(dijit._scopeName + ".Editor.getPlugin",[o]);
    	// Set the plug-in's context
    	plugin.setEditor(this); 
    	if(dojo.isFunction(plugin.setToolbar)){
    		plugin.setToolbar(this.toolbar);
    	}
    	...
    }

创建并初始化所有声明的插件。

创建自己的插件

如果Dojo工具包提供的插件不能满足您的需求,则可以构建自己的插件。 Dojo富文本编辑器使您可以扩展编辑器的功能。 您可以创建一个新的插件类,该类继承自dijit._editor._Plugin并将其添加到编辑器的插件列表中。

编辑器插件的生命周期

dijit._editor._Plugin是编辑器插件的基类,通常是工具栏上的单个按钮以及一些关联的代码。 它定义了插件的生命周期。

当插件的生命周期通过addPlugin函数添加到编辑器中时开始,从而发布Dojo主题,以便插件可以自行构造。 然后分别调用插件的setEditorsetToolbar函数,以将插件安装到编辑器中。 默认情况下, setEditor函数:

  1. 创建对编辑器的本地引用。
  2. 创建命令按钮。
  3. 将编辑器的execCommand方法连接到按钮。
  4. 将插件的updateState方法连接到编辑器。

这很简单。 setToolbar的默认行为甚至更简单:它将先前创建的命令按钮添加到工具栏。

至此,初始化完成,插件生命周期进入“无尽”事件驱动阶段,直到有人销毁整个编辑器并结束生命周期为止,该生命周期将调用插件的destroy方法。

总而言之,生命周期功能为:

  • Editor.addPlugin
    • 插件的构造函数
    • plugin.setEditor
    • plugin.setToolbar
  • 事件驱动阶段。 不断调用plugin.updateState
  • Editor.destroy
    • plugin.destroy

为了更好地了解细节,您将在以下各节中编写一个名为FindReplace的查找/替换插件。 FindReplace在编辑器中的文本中搜索给定的关键字,如果找到则将其突出显示。 它还支持用新内容替换关键字。 要实现该插件,您将设计一个特殊的工具栏,该工具栏在单击命令按钮时显示。

继承dijit._editor._Plugin

第一步是通过继承基类dijit._editor._Plugin来建立一个空代码框架,如清单6所示。

清单6.新插件的基本代码框架
dojo.provide("dojox.editor.plugins.FindReplace");

dojo.require("dijit._editor._Plugin");

dojo.declare("dojox.editor.plugins.FindReplace", dijit._editor._Plugin, {
	// When you click the command button, you show a toolbar, 
	// instead of executing some editor commands.
	useDefaultCommand: false,
	
	// You can just use the original method.	
	// setEditor: function(editor){},
	
	setToolbar: function(editorToolbar){
		this.inherited(arguments);
		
		//TODO: Create your additional find/replace toolbar here, 
		// and append it after the editor toolbar.
	},
	
	updateState: function(){
		// You don't need to handle anything when editor state is updated. 
		// So just leave this empty.
	},
	
	destroy: function(){
		this.inherited(arguments);
		
		//TODO: Remember to destroy the toolbar you created.
	}
});

// Register this plug-in so it can construct itself when the editor publishes a topic.
dojo.subscribe(dijit._scopeName + ".Editor.getPlugin", null, function(o){
	if(!o.plugin && o.args.name.toLowerCase() === "findreplace"){
		o.plugin = new dojox.editor.plugins.FindReplace({});
	}
});

扩展工具栏

第二项任务是在编辑器工具栏上创建一个按钮。 setEditor方法将自动为您执行此操作; 您需要做的就是使用不同的标签和图标。 清单7显示了最简单的方法。

清单7.在编辑器工具栏中创建一个ToggleButton
...
dojo.declare("dojox.editor.plugins.FindReplace", dijit._editor._Plugin, {
	...
	// You'd like to use a toggle button to show/hide your own find/replace toolbar.
	buttonClass: dijit.form.ToggleButton,
	
	// As long as you provide a command, the CSS class of the button icon will be 
	// generated automatically. For this one, it will be "dijitEditorFindReplace".
	command: "findReplace",

	// You can also use localization here.
	getLabel: function(){
		return "Find and Replace";
	},
	...
});
...

当您有CSS类dijitEditorFindReplace的背景图像时,您可以看到示例按钮,如图3所示。

图3.插件示例的新按钮
工具栏上的新按钮,显示新插件的查找/替换图标

下一步是创建查找/替换工具栏,并将其绑定到命令按钮。 您需要一个用于搜索字符串的字段,另一个用于替换字符串的字段,一个查找按钮和一个替换按钮。 如果要使其功能更强大,可以添加许多其他内容使其看起来更专业,例如“全部替换”按钮或“区分大小写搜索”和“向后搜索”复选框。 您可以编写一个简单的单独的小部件来容纳所有这些东西,如清单8所示。

清单8.创建一个查找/替换工具栏
dojo.declare("dojox.editor.plugins.FindReplacePane", [dijit._Widget, dijit._Templated], {
	// With templates, you don't need to create all the stuff manually.
	templateString: dojo.cache("dojox.editor.plugins", "FindReplacePane.html"),
	
	// There are widgets in template. Tell the parser to parse them.
	widgetsInTemplate: true
});

在FindReplacePane.html中,您可以直接使用dijit.Toolbar和其他表单小部件。 清单9中的示例将标签和文本字段(或复选框)组合在一起以形成一个新的小部件,以使代码更简单。

清单9.查找/替换工具栏的内容
<div><div dojotype="dijit.Toolbar" dojoattachpoint="frToolbar">
  <div dojoattachpoint="findField" dojotype="dojox.editor.plugins._FindReplaceTextBox" 
    label="Find:"></div>
  <div dojoattachpoint="replaceField" dojotype="dojox.editor.plugins._FindReplaceTextBox" 
    label="Replace with:"></div>
  <div dojotype="dojox.editor.plugins._ToolbarLineBreak"></div>
  <div dojoattachpoint="findButton" dojotype="dijit.form.Button" 
    label="Find" showLable="true"></div>
  <div dojoattachpoint="replaceButton" dojotype="dijit.form.Button" 
    label="Replace" showLable="true"></div>
  <div dojoattachpoint="replaceAllButton" dojotype="dijit.form.Button" 
    label="Replace All" showLable="true"></div>
  <div dojoattachpoint="matchCase" dojotype="dojox.editor.plugins._FindReplaceCheckBox" 
    label="Match case"></div>
  <div dojoattachpoint="backwards" dojotype="dojox.editor.plugins._FindReplaceCheckBox" 
    label="Backwards"></div>
</div></div>

使用dojoattachpoint您可以轻松地将小部​​件作为FindReplacePane的属性来FindReplacePanedojox.editor.plugins._ToolbarLineBreak是用于多行工具栏的非常有用的小部件。

现在您已经有了按钮和工具栏,是时候将它们连接在一起了。 您所要做的就是将工具栏放置在适当的位置,并定义单击切换按钮时的操作。 清单10显示了一个示例。

清单10.连接按钮和工具栏
// This initialization work should be done in setToolbar, 
// because you want to be sure that the editor toolbar is ready.
setToolbar: function(editorToolbar){
	// Super class will add the command button to the editor toolbar for you.
	this.inherited(arguments);
	
	// Create your find/replace toolbar, place it after the editor toolbar,
	// hide it, and start it up.
	var frtb = this.frToolbar = new dojox.editor.plugins.FindReplacePane();
	frtb.placeAt(toolbar.domNode, "after");
	dojo.style(frtb.domNode, "display", "none");
	frtb.startup();
	
	// Toggle it when your toggle button is clicked...
	this.connect(this.button, "onChange", "_toggleFindReplace");
	
	...
},
_toggleFindReplace: function(toShow){
	// Remember the original height.
	var height = dojo.marginBox(this.editor.domNode).h
	
	dojo.style(this.frToolbar.domNode, "display", toShow ? "block" : "none");
	
	// Resize the editor to maintain the height.
	this.editor.resize({h: height});
}

图4显示了您的示例现在的样子。

图4.查找/替换工具栏
工具栏上带有单词“查找和替换”以及每个文本框旁边的文本框,其中包含用于区分大小写和向后搜索的复选框。

处理事件并实现功能

现在,使“查找”和“替换”按钮正常工作。 您可以在setToolbar方法中进行设置,如清单11所示。

清单11.处理事件
setToolbar: function(editorToolbar){
	...
	var tb = this._frToolbar = ...
	
	// Connect methods to the onClick events of the buttons.
	this.connect(tb.findButton, "onClick", "_find");
	this.connect(tb.replaceButton, "onClick", "_replace");
	this.connect(tb.replaceAllButton, "onClick", "_replaceAll");
	
	// Make the ENTER key work for the "Find" text field.
	this.connect(tb.findField, "onKeyDown", function(evt){
		if(evt.keyCode == dojo.keys.ENTER){
			this._find();
			dojo.stopEvent(evt);
		}
	});
	
	...
}

那很简单。 下一步是实现_find函数。 对于非IE浏览器,您可以简单地使用window.find。 对于IE而言,情况变得有些复杂。 您需要编写一个适配器函数来消除浏览器的差异,如清单12所示。

清单12. Find的实现
// An adapter function to make all browsers look the same.
_findText: function(txt, isCaseSensitive, isBackwards){
	if(!txt){ return false; }
	var ed = this.editor, win = ed.window, doc = ed.document;
	var found = false;
	if(win.find){
		found = win.find(txt, isCaseSensitive, isBackwards, 
			false, false, false, false);
	}else if(doc.selection){
		/* IE */
		// Focus to restore position/selection, 
		// then shift to search from current position.
		ed.focus();
		var txtRg = doc.body.createTextRange();
		var curPos = doc.selection ? doc.selection.createRange() : null;
		if(curPos){
			txtRg.setEndPoint(isBackwards ? "EndToStart" : "StartToEnd", 
				curPos);
		}
		var flags = isCaseSensitive ? 4 : 0;
		if(backwards){
			flags = flags | 1;
		}
		found = txtRg.findText(txt, txtRg.text.length, flags);
		if(found){
			txtRg.select();
		}
	}
	return found;
},
_find: function(){
	var tb = this._frToolbar;
	return this._findText(tb.findField.get("value"), 
		tb.matchCase.get("value"), tb.backwards.get("value"));
}

再次运行页面以查看效果,如图5所示。

图5.查找文本
在浏览器窗口中找到单词列表。

现在,您可以在大多数现代浏览器上使用有用的“查找”功能。

以编程方式编辑内容

Dojo Rich Text Editor提供了一个统一的API execCommand ,您可以使用它来调用内置命令。 有许多命令可用,例如撤消,重做,剪切,复制,粘贴,粗体和斜体。 对于内置命令,请参阅dijit.Editor文档的完整列表(见相关主题 )。

对于示例插件,您需要在编辑器中插入一些文本以替换选定的文本。 当然,对此有一个内置命令— inserthtml 。 您所要做的就是:

  1. 检查所选文本是否与find字段中的文本匹配。
  2. 如果是,请调用editor.execCommand("inserthtml", replaceText);

清单13显示了代码。

清单13.替换实现
_replace: function(){
	var tb = this._frToolbar;
	var txt = tb.findField.get("value");
	if(!txt){ return false; }
	
	var repTxt = tb.replaceField.get("value") || "";
	var isCaseSensitive = tb.caseSensitive.get("value");
	var isBackwards = tb.backwards.get("value");
	var ed = this.editor;
	ed.focus();
	
	//Replace the current selected text if it matches the find field.
	var selected = dojo.withGlobal(ed.window, "getSelectedText", 
		dijit._editor.selection, [null]);
	if(selected && (isCaseSensitive ? 
		(selected === txt) : (selected.toLowerCase() === txt.toLowerCase()))){
		ed.execCommand("inserthtml", repTxt);
		return true;
	}
	return false;
}

您应该在编辑器中使用iframe窗口而不是整个页面的窗口来调用getSelectedText 。 图6显示了结果。

图6.替换文字
在浏览器窗口中找到单词列表,并将其替换为单词队列。

您现在知道编写编辑器插件的基本细节。 也许您可以继续自己执行全部替换功能。

结论

在本文中,您了解了Dojo Rich Text Editor的可插拔体系结构。 插件机制使您可以扩展编辑器的功能。 使用Dojo Rich Text Editor,您可以在应用程序中部署功能强大的文本编辑器。 您可以轻松使用和自定义编辑器以满足您的特定要求。


翻译自: https://www.ibm.com/developerworks/web/library/wa-master/index.html

dojo/text!.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>通过属性查询地图服务中的信息</title> <link rel="stylesheet" href="https://js.arcgis.com/3.39/esri/css/esri.css"> <!-- <link rel="stylesheet" type="text/css" href="./css/esri.css" /> --> <link rel="stylesheet" href="https://js.arcgis.com/3.40/esri/themes/calcite/dijit/calcite.css"> <script src="https://js.arcgis.com/3.41/"></script> <script> require(["esri/map", //加载地图组件 "dojo/dom", "dojo/on", "esri/InfoTemplate", "esri/graphic", "esri/geometry/Point",//加载点对象组件 "esri/symbols/SimpleMarkerSymbol", "esri/geometry/Extent",//加载范围组件 "esri/layers/FeatureLayer", //加载FeatureLayer地图组件 // "esri/dijit/FeatureTable", "esri/layers/WebTiledLayer", //加载切片地图组件 "esri/layers/ArcGISDynamicMapServiceLayer",//加载动态地图组件 "esri/symbols/SimpleFillSymbol", "esri/renderers/UniqueValueRenderer", "esri/tasks/query", "esri/tasks/QueryTask", "esri/Color", "dojo/domReady!" ], function (Map, dom, on, InfoTemplate, Graphic, Point, SimpleMarkerSymbol,Extent, FeatureLayer, WebTiledLayer, ArcGISDynamicMapServiceLayer, SimpleFillSymbol, UniqueValueRenderer, Query, QueryTask, Color, GeoJsonLayer) { //初始化地图容器 // map = new Map("map", { logo: false, slider: false }, {zoom: 8}); map = new Map("map", { center: [109.33789 , 29.57985], basemap: "satellite", zoom: 10, sliderStyle: "small", logo: false }); // 创建底图 var basemap = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"); map.addLayer(basemap,0); // 创建动态图层 var dynamicLayer = new ArcGISDynamicMapServiceLayer("http://116.62.63.94:6080/arcgis/rest/services/sanhuxiangtest/MapServer"); map.addLayer(dynamicLayer,99); }) </script> </head> <body class="tundra"> <div id="map" style="width:900px; height:580px; border:1px solid #000;"></div> 类别名称:<input class="nm" type="text"> </body> </html>
最新发布
07-15

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值