editHyperlinks.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /**
  2. * Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
  3. *
  4. * @licstart
  5. * This file is part of WebODF.
  6. *
  7. * WebODF is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU Affero General Public License (GNU AGPL)
  9. * as published by the Free Software Foundation, either version 3 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * WebODF is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with WebODF. If not, see <http://www.gnu.org/licenses/>.
  19. * @licend
  20. *
  21. * @source: http://www.webodf.org/
  22. * @source: https://github.com/kogmbh/WebODF/
  23. */
  24. /*global define, require, document, odf, runtime, core, gui */
  25. define("webodf/editor/widgets/editHyperlinks", [
  26. "webodf/editor/EditorSession",
  27. "webodf/editor/widgets/dialogWidgets/editHyperlinkPane",
  28. "dijit/form/Button",
  29. "dijit/form/DropDownButton",
  30. "dijit/TooltipDialog"],
  31. function (EditorSession, EditHyperlinkPane, Button, DropDownButton, TooltipDialog) {
  32. "use strict";
  33. runtime.loadClass("odf.OdfUtils");
  34. runtime.loadClass("odf.TextSerializer");
  35. runtime.loadClass("core.EventSubscriptions");
  36. var EditHyperlinks = function (callback) {
  37. var self = this,
  38. widget = {},
  39. editorSession,
  40. hyperlinkController,
  41. linkEditorContent,
  42. editHyperlinkButton,
  43. removeHyperlinkButton,
  44. odfUtils = odf.OdfUtils,
  45. textSerializer = new odf.TextSerializer(),
  46. eventSubscriptions = new core.EventSubscriptions(),
  47. dialog;
  48. function updateLinkEditorContent() {
  49. var selection = editorSession.getSelectedRange(),
  50. linksInSelection = editorSession.getSelectedHyperlinks(),
  51. linkTarget = linksInSelection[0] ? odfUtils.getHyperlinkTarget(linksInSelection[0]) : "http://";
  52. if (selection && selection.collapsed && linksInSelection.length === 1) {
  53. // Selection is collapsed within a single hyperlink. Assume user is modifying the hyperlink
  54. linkEditorContent.set({
  55. linkDisplayText: textSerializer.writeToString(linksInSelection[0]),
  56. linkUrl: linkTarget,
  57. isReadOnlyText: true
  58. });
  59. } else if (selection && !selection.collapsed) {
  60. // User has selected part of a hyperlink or a block of text. Assume user is attempting to modify the
  61. // existing hyperlink, or wants to convert the selection into a hyperlink
  62. linkEditorContent.set({
  63. // TODO Improve performance by rewriting to not clone the range contents
  64. linkDisplayText: textSerializer.writeToString(selection.cloneContents()),
  65. linkUrl: linkTarget,
  66. isReadOnlyText: true
  67. });
  68. } else {
  69. // Selection is collapsed and is not in an existing hyperlink
  70. linkEditorContent.set({
  71. linkDisplayText: "",
  72. linkUrl: linkTarget,
  73. isReadOnlyText: false
  74. });
  75. }
  76. }
  77. function updateHyperlinkButtons() {
  78. var controllerEnabled = hyperlinkController && hyperlinkController.isEnabled(),
  79. linksInSelection;
  80. // Enable to disable all widgets initially
  81. widget.children.forEach(function (element) {
  82. element.set('disabled', controllerEnabled !== true, false);
  83. });
  84. if (controllerEnabled) {
  85. // Specifically enable the remove hyperlink button only if there are links in the current selection
  86. linksInSelection = editorSession.getSelectedHyperlinks();
  87. removeHyperlinkButton.set('disabled', linksInSelection.length === 0, false);
  88. }
  89. }
  90. function updateSelectedLink(hyperlinkData) {
  91. var selection = editorSession.getSelectedRange(),
  92. selectionController = editorSession.sessionController.getSelectionController(),
  93. selectedLinkRange,
  94. linksInSelection = editorSession.getSelectedHyperlinks();
  95. if (hyperlinkData.isReadOnlyText === "true") {
  96. if (selection && selection.collapsed && linksInSelection.length === 1) {
  97. // Editing the single link the cursor is currently within
  98. selectedLinkRange = selection.cloneRange();
  99. selectedLinkRange.selectNode(linksInSelection[0]);
  100. selectionController.selectRange(selectedLinkRange, true);
  101. }
  102. hyperlinkController.removeHyperlinks();
  103. hyperlinkController.addHyperlink(hyperlinkData.linkUrl);
  104. } else {
  105. hyperlinkController.addHyperlink(hyperlinkData.linkUrl, hyperlinkData.linkDisplayText);
  106. linksInSelection = editorSession.getSelectedHyperlinks();
  107. selectedLinkRange = selection.cloneRange();
  108. selectedLinkRange.selectNode(linksInSelection[0]);
  109. selectionController.selectRange(selectedLinkRange, true);
  110. }
  111. }
  112. this.setEditorSession = function (session) {
  113. eventSubscriptions.unsubscribeAll();
  114. hyperlinkController = undefined;
  115. editorSession = session;
  116. if (editorSession) {
  117. hyperlinkController = editorSession.sessionController.getHyperlinkController();
  118. eventSubscriptions.addFrameSubscription(editorSession, EditorSession.signalCursorMoved, updateHyperlinkButtons);
  119. eventSubscriptions.addFrameSubscription(editorSession, EditorSession.signalParagraphChanged, updateHyperlinkButtons);
  120. eventSubscriptions.addFrameSubscription(editorSession, EditorSession.signalParagraphStyleModified, updateHyperlinkButtons);
  121. eventSubscriptions.addSubscription(hyperlinkController, gui.HyperlinkController.enabledChanged, updateHyperlinkButtons);
  122. }
  123. updateHyperlinkButtons();
  124. };
  125. /*jslint emptyblock: true*/
  126. this.onToolDone = function () {};
  127. /*jslint emptyblock: false*/
  128. function init() {
  129. textSerializer.filter = new odf.OdfNodeFilter();
  130. linkEditorContent = new EditHyperlinkPane();
  131. dialog = new TooltipDialog({
  132. title: runtime.tr("Edit link"),
  133. content: linkEditorContent.widget(),
  134. onShow: updateLinkEditorContent
  135. });
  136. editHyperlinkButton = new DropDownButton({
  137. label: runtime.tr('Edit link'),
  138. showLabel: false,
  139. disabled: true,
  140. iconClass: 'dijitEditorIcon dijitEditorIconCreateLink',
  141. dropDown: dialog
  142. });
  143. removeHyperlinkButton = new Button({
  144. label: runtime.tr('Remove link'),
  145. showLabel: false,
  146. disabled: true,
  147. iconClass: 'dijitEditorIcon dijitEditorIconUnlink',
  148. onClick: function () {
  149. hyperlinkController.removeHyperlinks();
  150. self.onToolDone();
  151. }
  152. });
  153. linkEditorContent.onSave = function () {
  154. var hyperlinkData = linkEditorContent.value();
  155. editHyperlinkButton.closeDropDown(false);
  156. updateSelectedLink(hyperlinkData);
  157. self.onToolDone();
  158. };
  159. linkEditorContent.onCancel = function () {
  160. editHyperlinkButton.closeDropDown(false);
  161. self.onToolDone();
  162. };
  163. widget.children = [editHyperlinkButton, removeHyperlinkButton];
  164. widget.startup = function () {
  165. widget.children.forEach(function (element) {
  166. element.startup();
  167. });
  168. };
  169. widget.placeAt = function (container) {
  170. widget.children.forEach(function (element) {
  171. element.placeAt(container);
  172. });
  173. return widget;
  174. };
  175. callback(widget);
  176. }
  177. init();
  178. };
  179. return EditHyperlinks;
  180. });