Source: control/control.js

  1. import OLControl from 'ol/control/Control';
  2. import VectorSource from 'ol/source/Vector';
  3. /**
  4. * OLE control base class.
  5. * @extends ol.control.Control
  6. * @alias ole.Control
  7. */
  8. class Control extends OLControl {
  9. /**
  10. * @inheritdoc
  11. * @param {Object} options Control options.
  12. * @param {HTMLElement} options.element Element which to substitute button. Set to null if you don't want to display an html element.
  13. * @param {string} options.className Name of the control's HTML class.
  14. * @param {string} options.title Title of the control toolbar button.
  15. * @param {Image} options.image Control toolbar image.
  16. * @param {HTMLElement} [options.dialogTarget] Specify a target if you want
  17. * the dialog div used by the control to be rendered outside of the map's viewport. Set tio null if you don't want to display the dialog of a control.
  18. * @param {ol.source.Vector} [options.source] Vector source holding
  19. * edit features. If undefined, options.features must be passed.
  20. * @param {ol.Collection<ol.Feature>} [options.features] Collection of
  21. * edit features. If undefined, options.source must be set.
  22. * @param {function} [options.layerFilter] Filter editable layer.
  23. */
  24. constructor(options) {
  25. let button = null;
  26. if (options.element !== null && !options.element) {
  27. button = document.createElement('button');
  28. button.className = `ole-control ${options.className}`;
  29. }
  30. super({
  31. element:
  32. options.element === null
  33. ? document.createElement('div') // An element must be define otherwise ol complains, when we add control
  34. : options.element || button,
  35. });
  36. /**
  37. * Specify a target if you want the dialog div used by the
  38. * control to be rendered outside of the map's viewport.
  39. * @type {HTMLElement}
  40. * @private
  41. */
  42. this.dialogTarget = options.dialogTarget;
  43. /**
  44. * Control properties.
  45. * @type {object}
  46. * @private
  47. */
  48. this.properties = { ...options };
  49. /**
  50. * Html class name of the control button.
  51. * @type {string}
  52. * @private
  53. */
  54. this.className = options.className;
  55. /**
  56. * Control title.
  57. * @type {string}
  58. * @private
  59. */
  60. this.title = options.title;
  61. if (button) {
  62. const img = document.createElement('img');
  63. img.src = options.image;
  64. button.appendChild(img);
  65. button.title = this.title;
  66. button.addEventListener('click', this.onClick.bind(this));
  67. }
  68. /**
  69. * Source with edit features.
  70. * @type {ol.source.Vector}
  71. * @private
  72. */
  73. this.source =
  74. options.source ||
  75. new VectorSource({
  76. features: options.features,
  77. });
  78. /**
  79. * Filter editable layer. Used by select interactions instead of
  80. * the old source property.
  81. * @type {function}
  82. * @private
  83. */
  84. this.layerFilter =
  85. options.layerFilter ||
  86. ((layer) => !this.source || (layer && layer.getSource() === this.source));
  87. /**
  88. * ole.Editor instance.
  89. * @type {ole.Editor}
  90. * @private
  91. */
  92. this.editor = null;
  93. /**
  94. * @type {Boolean}
  95. * @private
  96. */
  97. this.standalone = true;
  98. }
  99. /**
  100. * Returns the control's element.
  101. * @returns {Element} the control element.
  102. */
  103. getElement() {
  104. return this.element;
  105. }
  106. /**
  107. * Click handler for the control element.
  108. * @private
  109. */
  110. onClick() {
  111. if (this.active) {
  112. this.deactivate();
  113. } else {
  114. this.activate();
  115. }
  116. }
  117. /**
  118. * Sets the map of the control.
  119. * @protected
  120. * @param {ol.Map} map The map object.
  121. */
  122. setMap(map) {
  123. this.map = map;
  124. super.setMap(this.map);
  125. }
  126. /**
  127. * Introduce the control to it's editor.
  128. * @param {ole.Editor} editor OLE Editor.
  129. * @protected
  130. */
  131. setEditor(editor) {
  132. this.editor = editor;
  133. }
  134. /**
  135. * Activate the control
  136. */
  137. activate(silent) {
  138. this.active = true;
  139. if (this.element) {
  140. this.element.className += ' active';
  141. }
  142. if (!silent) {
  143. this.dispatchEvent({
  144. type: 'change:active',
  145. target: this,
  146. detail: { control: this },
  147. });
  148. }
  149. this.openDialog();
  150. }
  151. /**
  152. * Dectivate the control
  153. * @param {boolean} [silent] Do not trigger an event.
  154. */
  155. deactivate(silent) {
  156. this.active = false;
  157. if (this.element) {
  158. this.element.classList.remove('active');
  159. }
  160. if (!silent) {
  161. this.dispatchEvent({
  162. type: 'change:active',
  163. target: this,
  164. detail: { control: this },
  165. });
  166. }
  167. this.closeDialog();
  168. }
  169. /**
  170. * Returns the active state of the control.
  171. * @returns {Boolean} Active state.
  172. */
  173. getActive() {
  174. return this.active;
  175. }
  176. /**
  177. * Open the control's dialog (if defined).
  178. */
  179. openDialog() {
  180. this.closeDialog();
  181. if (this.dialogTarget !== null && this.getDialogTemplate) {
  182. this.dialogDiv = document.createElement('div');
  183. this.dialogDiv.innerHTML = `
  184. <div class="ole-dialog">
  185. ${this.getDialogTemplate()}
  186. </div>
  187. `;
  188. (this.dialogTarget || this.map.getTargetElement()).appendChild(
  189. this.dialogDiv,
  190. );
  191. }
  192. }
  193. /**
  194. * Closes the control dialog.
  195. * @private
  196. */
  197. closeDialog() {
  198. if (this.dialogDiv) {
  199. (this.dialogTarget || this.map.getTargetElement()).removeChild(
  200. this.dialogDiv,
  201. );
  202. this.dialogDiv = null;
  203. }
  204. }
  205. /**
  206. * Set properties.
  207. * @param {object} properties New control properties.
  208. * @param {boolean} [silent] If true, no propertychange event is triggered.
  209. */
  210. setProperties(properties, silent) {
  211. this.properties = { ...this.properties, ...properties };
  212. if (!silent) {
  213. this.dispatchEvent({
  214. type: 'propertychange',
  215. target: this,
  216. detail: { properties: this.properties, control: this },
  217. });
  218. }
  219. }
  220. /**
  221. * Return properties.
  222. * @returns {object} Copy of control properties.
  223. */
  224. getProperties() {
  225. return { ...this.properties };
  226. }
  227. }
  228. export default Control;