LinkDialog.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dijit._editor.plugins.LinkDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dijit._editor.plugins.LinkDialog"] = true;
  8. dojo.provide("dijit._editor.plugins.LinkDialog");
  9. dojo.require("dijit._Widget");
  10. dojo.require("dijit._editor._Plugin");
  11. dojo.require("dijit.TooltipDialog");
  12. dojo.require("dijit.form.DropDownButton");
  13. dojo.require("dijit.form.ValidationTextBox");
  14. dojo.require("dijit.form.Select");
  15. dojo.require("dijit._editor.range");
  16. dojo.require("dojo.i18n");
  17. dojo.require("dojo.string");
  18. dojo.requireLocalization("dijit", "common", null, "ROOT,ar,az,bg,ca,cs,da,de,el,es,fi,fr,he,hr,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw");
  19. dojo.requireLocalization("dijit._editor", "LinkDialog", null, "ROOT,ar,az,bg,ca,cs,da,de,el,es,fi,fr,he,hr,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw");
  20. dojo.declare("dijit._editor.plugins.LinkDialog", dijit._editor._Plugin, {
  21. // summary:
  22. // This plugin provides the basis for an 'anchor' (link) dialog and an extension of it
  23. // provides the image link dialog.
  24. //
  25. // description:
  26. // The command provided by this plugin is:
  27. // * createLink
  28. // Override _Plugin.buttonClass. This plugin is controlled by a DropDownButton
  29. // (which triggers a TooltipDialog).
  30. buttonClass: dijit.form.DropDownButton,
  31. // Override _Plugin.useDefaultCommand... processing is handled by this plugin, not by dijit.Editor.
  32. useDefaultCommand: false,
  33. // urlRegExp: [protected] String
  34. // Used for validating input as correct URL. While file:// urls are not terribly
  35. // useful, they are technically valid.
  36. urlRegExp: "((https?|ftps?|file)\\://|\./|/|)(/[a-zA-Z]{1,1}:/|)(((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)*(?:[a-zA-Z](?:[-\\da-zA-Z]{0,80}[\\da-zA-Z])?)\\.?)|(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])|(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]|(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]|(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[01]\\d{2}|42949672[0-8]\\d|429496729[0-5])|0[xX]0*[\\da-fA-F]{1,8}|([\\da-fA-F]{1,4}\\:){7}[\\da-fA-F]{1,4}|([\\da-fA-F]{1,4}\\:){6}((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])))(\\:\\d+)?(/(?:[^?#\\s/]+/)*(?:[^?#\\s/]{0,}(?:\\?[^?#\\s/]*)?(?:#.*)?)?)?",
  37. // emailRegExp: [protected] String
  38. // Used for validating input as correct email address. Taken from dojox.validate
  39. emailRegExp: "<?(mailto\\:)([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+" /*username*/ + "@" +
  40. "((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)+(?:[a-zA-Z](?:[-\\da-zA-Z]{0,6}[\\da-zA-Z])?)\\.?)|localhost|^[^-][a-zA-Z0-9_-]*>?", // host.
  41. // htmlTemplate: [protected] String
  42. // String used for templating the HTML to insert at the desired point.
  43. htmlTemplate: "<a href=\"${urlInput}\" _djrealurl=\"${urlInput}\"" +
  44. " target=\"${targetSelect}\"" +
  45. ">${textInput}</a>",
  46. // tag: [protected] String
  47. // Tag used for the link type.
  48. tag: "a",
  49. // _hostRxp [private] RegExp
  50. // Regular expression used to validate url fragments (ip address, hostname, etc)
  51. _hostRxp: new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"),
  52. // _userAtRxp [private] RegExp
  53. // Regular expression used to validate e-mail address fragment.
  54. _userAtRxp: new RegExp("^([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+@", "i"),
  55. // linkDialogTemplate: [protected] String
  56. // Template for contents of TooltipDialog to pick URL
  57. linkDialogTemplate: [
  58. "<table><tr><td>",
  59. "<label for='${id}_urlInput'>${url}</label>",
  60. "</td><td>",
  61. "<input dojoType='dijit.form.ValidationTextBox' required='true' " +
  62. "id='${id}_urlInput' name='urlInput' intermediateChanges='true'/>",
  63. "</td></tr><tr><td>",
  64. "<label for='${id}_textInput'>${text}</label>",
  65. "</td><td>",
  66. "<input dojoType='dijit.form.ValidationTextBox' required='true' id='${id}_textInput' " +
  67. "name='textInput' intermediateChanges='true'/>",
  68. "</td></tr><tr><td>",
  69. "<label for='${id}_targetSelect'>${target}</label>",
  70. "</td><td>",
  71. "<select id='${id}_targetSelect' name='targetSelect' dojoType='dijit.form.Select'>",
  72. "<option selected='selected' value='_self'>${currentWindow}</option>",
  73. "<option value='_blank'>${newWindow}</option>",
  74. "<option value='_top'>${topWindow}</option>",
  75. "<option value='_parent'>${parentWindow}</option>",
  76. "</select>",
  77. "</td></tr><tr><td colspan='2'>",
  78. "<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>",
  79. "<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${buttonCancel}</button>",
  80. "</td></tr></table>"
  81. ].join(""),
  82. _initButton: function(){
  83. // Override _Plugin._initButton() to initialize DropDownButton and TooltipDialog.
  84. var _this = this;
  85. this.tag = this.command == 'insertImage' ? 'img' : 'a';
  86. var messages = dojo.mixin(dojo.i18n.getLocalization("dijit", "common", this.lang),
  87. dojo.i18n.getLocalization("dijit._editor", "LinkDialog", this.lang));
  88. var dropDown = (this.dropDown = new dijit.TooltipDialog({
  89. title: messages[this.command + "Title"],
  90. execute: dojo.hitch(this, "setValue"),
  91. onOpen: function(){
  92. _this._onOpenDialog();
  93. dijit.TooltipDialog.prototype.onOpen.apply(this, arguments);
  94. },
  95. onCancel: function(){
  96. setTimeout(dojo.hitch(_this, "_onCloseDialog"),0);
  97. }
  98. }));
  99. messages.urlRegExp = this.urlRegExp;
  100. messages.id = dijit.getUniqueId(this.editor.id);
  101. this._uniqueId = messages.id;
  102. this._setContent(dropDown.title +
  103. "<div style='border-bottom: 1px black solid;padding-bottom:2pt;margin-bottom:4pt'></div>" +
  104. dojo.string.substitute(this.linkDialogTemplate, messages));
  105. dropDown.startup();
  106. this._urlInput = dijit.byId(this._uniqueId + "_urlInput");
  107. this._textInput = dijit.byId(this._uniqueId + "_textInput");
  108. this._setButton = dijit.byId(this._uniqueId + "_setButton");
  109. this.connect(dijit.byId(this._uniqueId + "_cancelButton"), "onClick", function(){
  110. this.dropDown.onCancel();
  111. });
  112. if(this._urlInput){
  113. this.connect(this._urlInput, "onChange", "_checkAndFixInput");
  114. }
  115. if(this._textInput){
  116. this.connect(this._textInput, "onChange", "_checkAndFixInput");
  117. }
  118. // Build up the dual check for http/https/file:, and mailto formats.
  119. this._urlRegExp = new RegExp("^" + this.urlRegExp + "$", "i");
  120. this._emailRegExp = new RegExp("^" + this.emailRegExp + "$", "i");
  121. this._urlInput.isValid = dojo.hitch(this, function(){
  122. // Function over-ride of isValid to test if the input matches a url or a mailto style link.
  123. var value = this._urlInput.get("value");
  124. return this._urlRegExp.test(value) || this._emailRegExp.test(value);
  125. });
  126. this._connectTagEvents();
  127. this.inherited(arguments);
  128. },
  129. _checkAndFixInput: function(){
  130. // summary:
  131. // A function to listen for onChange events and test the input contents
  132. // for valid information, such as valid urls with http/https/ftp and if
  133. // not present, try and guess if the input url is relative or not, and if
  134. // not, append http:// to it. Also validates other fields as determined by
  135. // the internal _isValid function.
  136. var self = this;
  137. var url = this._urlInput.get("value");
  138. var fixupUrl = function(url){
  139. var appendHttp = false;
  140. var appendMailto = false;
  141. if(url && url.length > 1){
  142. url = dojo.trim(url);
  143. if(url.indexOf("mailto:") !== 0){
  144. if(url.indexOf("/") > 0){
  145. if(url.indexOf("://") === -1){
  146. // Check that it doesn't start with / or ./, which would
  147. // imply 'target server relativeness'
  148. if(url.charAt(0) !== '/' && url.indexOf("./") !== 0){
  149. if(self._hostRxp.test(url)){
  150. appendHttp = true;
  151. }
  152. }
  153. }
  154. }else if(self._userAtRxp.test(url)){
  155. // If it looks like a foo@, append a mailto.
  156. appendMailto = true;
  157. }
  158. }
  159. }
  160. if(appendHttp){
  161. self._urlInput.set("value", "http://" + url);
  162. }
  163. if(appendMailto){
  164. self._urlInput.set("value", "mailto:" + url);
  165. }
  166. self._setButton.set("disabled", !self._isValid());
  167. };
  168. if(this._delayedCheck){
  169. clearTimeout(this._delayedCheck);
  170. this._delayedCheck = null;
  171. }
  172. this._delayedCheck = setTimeout(function(){
  173. fixupUrl(url);
  174. }, 250);
  175. },
  176. _connectTagEvents: function(){
  177. // summary:
  178. // Over-ridable function that connects tag specific events.
  179. this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
  180. this.connect(this.editor.editNode, "ondblclick", this._onDblClick);
  181. }));
  182. },
  183. _isValid: function(){
  184. // summary:
  185. // Internal function to allow validating of the inputs
  186. // for a link to determine if set should be disabled or not
  187. // tags:
  188. // protected
  189. return this._urlInput.isValid() && this._textInput.isValid();
  190. },
  191. _setContent: function(staticPanel){
  192. // summary:
  193. // Helper for _initButton above. Not sure why it's a separate method.
  194. this.dropDown.set({
  195. parserScope: "dojo", // make parser search for dojoType/data-dojo-type even if page is multi-version
  196. content: staticPanel
  197. });
  198. },
  199. _checkValues: function(args){
  200. // summary:
  201. // Function to check the values in args and 'fix' them up as needed.
  202. // args: Object
  203. // Content being set.
  204. // tags:
  205. // protected
  206. if(args && args.urlInput){
  207. args.urlInput = args.urlInput.replace(/"/g, "&quot;");
  208. }
  209. return args;
  210. },
  211. setValue: function(args){
  212. // summary:
  213. // Callback from the dialog when user presses "set" button.
  214. // tags:
  215. // private
  216. //TODO: prevent closing popup if the text is empty
  217. this._onCloseDialog();
  218. if(dojo.isIE < 9){ //see #4151
  219. var sel = dijit.range.getSelection(this.editor.window);
  220. var range = sel.getRangeAt(0);
  221. var a = range.endContainer;
  222. if(a.nodeType === 3){
  223. // Text node, may be the link contents, so check parent.
  224. // This plugin doesn't really support nested HTML elements
  225. // in the link, it assumes all link content is text.
  226. a = a.parentNode;
  227. }
  228. if(a && (a.nodeName && a.nodeName.toLowerCase() !== this.tag)){
  229. // Stll nothing, one last thing to try on IE, as it might be 'img'
  230. // and thus considered a control.
  231. a = dojo.withGlobal(this.editor.window,
  232. "getSelectedElement", dijit._editor.selection, [this.tag]);
  233. }
  234. if(a && (a.nodeName && a.nodeName.toLowerCase() === this.tag)){
  235. // Okay, we do have a match. IE, for some reason, sometimes pastes before
  236. // instead of removing the targetted paste-over element, so we unlink the
  237. // old one first. If we do not the <a> tag remains, but it has no content,
  238. // so isn't readily visible (but is wrong for the action).
  239. if(this.editor.queryCommandEnabled("unlink")){
  240. // Select all the link childent, then unlink. The following insert will
  241. // then replace the selected text.
  242. dojo.withGlobal(this.editor.window,
  243. "selectElementChildren", dijit._editor.selection, [a]);
  244. this.editor.execCommand("unlink");
  245. }
  246. }
  247. }
  248. // make sure values are properly escaped, etc.
  249. args = this._checkValues(args);
  250. this.editor.execCommand('inserthtml',
  251. dojo.string.substitute(this.htmlTemplate, args));
  252. // IE sometimes leaves a blank link, so we need to fix it up.
  253. // Go ahead and do this for everyone just to avoid blank links
  254. // in the page.
  255. dojo.query("a", this.editor.document).forEach(function(a){
  256. if(!a.innerHTML && !domAttr.has(a, "name")){
  257. // Remove empty anchors that do not have "name" set.
  258. // Empty ones with a name set could be a hidden hash
  259. // anchor.
  260. a.parentNode.removeChild(a);
  261. }
  262. }, this);
  263. },
  264. _onCloseDialog: function(){
  265. // summary:
  266. // Handler for close event on the dialog
  267. this.editor.focus();
  268. },
  269. _getCurrentValues: function(a){
  270. // summary:
  271. // Over-ride for getting the values to set in the dropdown.
  272. // a:
  273. // The anchor/link to process for data for the dropdown.
  274. // tags:
  275. // protected
  276. var url, text, target;
  277. if(a && a.tagName.toLowerCase() === this.tag){
  278. url = a.getAttribute('_djrealurl') || a.getAttribute('href');
  279. target = a.getAttribute('target') || "_self";
  280. text = a.textContent || a.innerText;
  281. dojo.withGlobal(this.editor.window, "selectElement", dijit._editor.selection, [a, true]);
  282. }else{
  283. text = dojo.withGlobal(this.editor.window, dijit._editor.selection.getSelectedText);
  284. }
  285. return {urlInput: url || '', textInput: text || '', targetSelect: target || ''}; //Object;
  286. },
  287. _onOpenDialog: function(){
  288. // summary:
  289. // Handler for when the dialog is opened.
  290. // If the caret is currently in a URL then populate the URL's info into the dialog.
  291. var a;
  292. if(dojo.isIE < 9){
  293. // IE is difficult to select the element in, using the range unified
  294. // API seems to work reasonably well.
  295. var sel = dijit.range.getSelection(this.editor.window);
  296. var range = sel.getRangeAt(0);
  297. a = range.endContainer;
  298. if(a.nodeType === 3){
  299. // Text node, may be the link contents, so check parent.
  300. // This plugin doesn't really support nested HTML elements
  301. // in the link, it assumes all link content is text.
  302. a = a.parentNode;
  303. }
  304. if(a && (a.nodeName && a.nodeName.toLowerCase() !== this.tag)){
  305. // Stll nothing, one last thing to try on IE, as it might be 'img'
  306. // and thus considered a control.
  307. a = dojo.withGlobal(this.editor.window,
  308. "getSelectedElement", dijit._editor.selection, [this.tag]);
  309. }
  310. }else{
  311. a = dojo.withGlobal(this.editor.window,
  312. "getAncestorElement", dijit._editor.selection, [this.tag]);
  313. }
  314. this.dropDown.reset();
  315. this._setButton.set("disabled", true);
  316. this.dropDown.set("value", this._getCurrentValues(a));
  317. },
  318. _onDblClick: function(e){
  319. // summary:
  320. // Function to define a behavior on double clicks on the element
  321. // type this dialog edits to select it and pop up the editor
  322. // dialog.
  323. // e: Object
  324. // The double-click event.
  325. // tags:
  326. // protected.
  327. if(e && e.target){
  328. var t = e.target;
  329. var tg = t.tagName? t.tagName.toLowerCase() : "";
  330. if(tg === this.tag && dojo.attr(t,"href")){
  331. dojo.withGlobal(this.editor.window,
  332. "selectElement",
  333. dijit._editor.selection, [t]);
  334. this.editor.onDisplayChanged();
  335. setTimeout(dojo.hitch(this, function(){
  336. // Focus shift outside the event handler.
  337. // IE doesn't like focus changes in event handles.
  338. this.button.set("disabled", false);
  339. this.button.openDropDown();
  340. }), 10);
  341. }
  342. }
  343. }
  344. });
  345. dojo.declare("dijit._editor.plugins.ImgLinkDialog", [dijit._editor.plugins.LinkDialog], {
  346. // summary:
  347. // This plugin extends LinkDialog and adds in a plugin for handling image links.
  348. // provides the image link dialog.
  349. //
  350. // description:
  351. // The command provided by this plugin is:
  352. // * insertImage
  353. // linkDialogTemplate: [protected] String
  354. // Over-ride for template since img dialog doesn't need target that anchor tags may.
  355. linkDialogTemplate: [
  356. "<table><tr><td>",
  357. "<label for='${id}_urlInput'>${url}</label>",
  358. "</td><td>",
  359. "<input dojoType='dijit.form.ValidationTextBox' regExp='${urlRegExp}' " +
  360. "required='true' id='${id}_urlInput' name='urlInput' intermediateChanges='true'/>",
  361. "</td></tr><tr><td>",
  362. "<label for='${id}_textInput'>${text}</label>",
  363. "</td><td>",
  364. "<input dojoType='dijit.form.ValidationTextBox' required='false' id='${id}_textInput' " +
  365. "name='textInput' intermediateChanges='true'/>",
  366. "</td></tr><tr><td>",
  367. "</td><td>",
  368. "</td></tr><tr><td colspan='2'>",
  369. "<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>",
  370. "<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${buttonCancel}</button>",
  371. "</td></tr></table>"
  372. ].join(""),
  373. // htmlTemplate: [protected] String
  374. // String used for templating the <img> HTML to insert at the desired point.
  375. htmlTemplate: "<img src=\"${urlInput}\" _djrealurl=\"${urlInput}\" alt=\"${textInput}\" />",
  376. // tag: [protected] String
  377. // Tag used for the link type (img).
  378. tag: "img",
  379. _getCurrentValues: function(img){
  380. // summary:
  381. // Over-ride for getting the values to set in the dropdown.
  382. // a:
  383. // The anchor/link to process for data for the dropdown.
  384. // tags:
  385. // protected
  386. var url, text;
  387. if(img && img.tagName.toLowerCase() === this.tag){
  388. url = img.getAttribute('_djrealurl') || img.getAttribute('src');
  389. text = img.getAttribute('alt');
  390. dojo.withGlobal(this.editor.window,
  391. "selectElement", dijit._editor.selection, [img, true]);
  392. }else{
  393. text = dojo.withGlobal(this.editor.window, dijit._editor.selection.getSelectedText);
  394. }
  395. return {urlInput: url || '', textInput: text || ''}; //Object;
  396. },
  397. _isValid: function(){
  398. // summary:
  399. // Over-ride for images. You can have alt text of blank, it is valid.
  400. // tags:
  401. // protected
  402. return this._urlInput.isValid();
  403. },
  404. _connectTagEvents: function(){
  405. // summary:
  406. // Over-ridable function that connects tag specific events.
  407. this.inherited(arguments);
  408. this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
  409. // Use onmousedown instead of onclick. Seems that IE eats the first onclick
  410. // to wrap it in a selector box, then the second one acts as onclick. See #10420
  411. this.connect(this.editor.editNode, "onmousedown", this._selectTag);
  412. }));
  413. },
  414. _selectTag: function(e){
  415. // summary:
  416. // A simple event handler that lets me select an image if it is clicked on.
  417. // makes it easier to select images in a standard way across browsers. Otherwise
  418. // selecting an image for edit becomes difficult.
  419. // e: Event
  420. // The mousedown event.
  421. // tags:
  422. // private
  423. if(e && e.target){
  424. var t = e.target;
  425. var tg = t.tagName? t.tagName.toLowerCase() : "";
  426. if(tg === this.tag){
  427. dojo.withGlobal(this.editor.window,
  428. "selectElement",
  429. dijit._editor.selection, [t]);
  430. }
  431. }
  432. },
  433. _checkValues: function(args){
  434. // summary:
  435. // Function to check the values in args and 'fix' them up as needed
  436. // (special characters in the url or alt text)
  437. // args: Object
  438. // Content being set.
  439. // tags:
  440. // protected
  441. if(args && args.urlInput){
  442. args.urlInput = args.urlInput.replace(/"/g, "&quot;");
  443. }
  444. if(args && args.textInput){
  445. args.textInput = args.textInput.replace(/"/g, "&quot;");
  446. }
  447. return args;
  448. },
  449. _onDblClick: function(e){
  450. // summary:
  451. // Function to define a behavior on double clicks on the element
  452. // type this dialog edits to select it and pop up the editor
  453. // dialog.
  454. // e: Object
  455. // The double-click event.
  456. // tags:
  457. // protected.
  458. if(e && e.target){
  459. var t = e.target;
  460. var tg = t.tagName? t.tagName.toLowerCase() : "";
  461. if(tg === this.tag && dojo.attr(t,"src")){
  462. dojo.withGlobal(this.editor.window,
  463. "selectElement",
  464. dijit._editor.selection, [t]);
  465. this.editor.onDisplayChanged();
  466. setTimeout(dojo.hitch(this, function(){
  467. // Focus shift outside the event handler.
  468. // IE doesn't like focus changes in event handles.
  469. this.button.set("disabled", false);
  470. this.button.openDropDown();
  471. }), 10);
  472. }
  473. }
  474. }
  475. });
  476. // Register this plugin.
  477. dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
  478. if(o.plugin){ return; }
  479. switch(o.args.name){
  480. case "createLink":
  481. o.plugin = new dijit._editor.plugins.LinkDialog({command: o.args.name});
  482. break;
  483. case "insertImage":
  484. o.plugin = new dijit._editor.plugins.ImgLinkDialog({command: o.args.name});
  485. break;
  486. }
  487. });
  488. }