openlayers_behavior_geofield.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. * @file
  3. * JS Implementation of OpenLayers behavior.
  4. */
  5. /**
  6. * Class: OpenLayers.Control.DrupalEditingToolbar
  7. * The DrupalEditingToolbar is a panel controls to modify or draw polygons, lines,
  8. * points, or to navigate the map by panning. You can select which tool to enable
  9. * with options.tools.
  10. *
  11. * Inherits from:
  12. * - <OpenLayers.Control.Panel>
  13. */
  14. OpenLayers.Control.GeofieldEditingToolbar = OpenLayers.Class(
  15. OpenLayers.Control.Panel, {
  16. /**
  17. * Constructor: OpenLayers.Control.EditingToolbar
  18. * Create an editing toolbar for a given layer.
  19. *
  20. * Parameters:
  21. * layer - {<OpenLayers.Layer.Vector>}
  22. * options - {Object}
  23. */
  24. initialize: function(layer, options) {
  25. OpenLayers.Control.Panel.prototype.initialize.apply(this, [options]);
  26. var controls = [];
  27. var tools = options.tools;
  28. var tool = null;
  29. if (tools && tools.length) {
  30. for (var i = 0, il = tools.length; i < il; i += 1) {
  31. // capitalize first letter
  32. tool = tools[i][0].toUpperCase() + tools[i].slice(1);
  33. controls.push(
  34. new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler[tool], {'displayClass': 'olControlDrawFeature' + tool})
  35. );
  36. }
  37. }
  38. if (options.allow_edit && options.allow_edit !== 0) {
  39. // add an Edit feature
  40. controls.push(new OpenLayers.Control.ModifyFeature(layer, {
  41. deleteCodes: [46, 68, 100],
  42. handleKeypress: function(evt) {
  43. if (this.feature && OpenLayers.Util.indexOf(this.deleteCodes, evt.keyCode) > -1) {
  44. // We must unselect the feature before we delete it
  45. var feature_to_delete = this.feature;
  46. this.selectControl.unselectAll();
  47. this.layer.removeFeatures([feature_to_delete]);
  48. }
  49. }
  50. }));
  51. }
  52. this.addControls(controls);
  53. },
  54. /**
  55. * Method: draw
  56. * calls the default draw, and then activates mouse defaults.
  57. *
  58. * Returns:
  59. * {DOMElement}
  60. */
  61. draw: function() {
  62. var div = OpenLayers.Control.Panel.prototype.draw.apply(this, arguments);
  63. if (this.defaultControl === null) {
  64. this.defaultControl = this.controls[0];
  65. }
  66. return div;
  67. },
  68. CLASS_NAME: "OpenLayers.Control.EditingToolbar"
  69. });
  70. (function($) {
  71. /**
  72. * Geofield Behavior
  73. */
  74. Drupal.behaviors.openlayers_behavior_geofield = {
  75. 'attach': function(context, settings) {
  76. var data = $(context).data('openlayers'),
  77. behavior = data && data.map.behaviors['openlayers_behavior_geofield'],
  78. dataProjection = new OpenLayers.Projection('EPSG:4326'),
  79. features, wktFormat;
  80. // helper to create a WKT format object with the right projections
  81. function initWktFormat (inp, outp) {
  82. var WktWriter = new OpenLayers.Format.WKT();
  83. WktWriter.internalProjection = inp;
  84. WktWriter.externalProjection = outp || dataProjection;
  85. return WktWriter;
  86. }
  87. // populate our wkt input field
  88. function updateWKTField (features) {
  89. var WktWriter = initWktFormat(features.object.map.projection);
  90. // limits are to be checked server-side, not here.
  91. // for a single shape avoid GEOMETRYCOLLECTION
  92. var toSerialize = features.object.features;
  93. // don't serialize empty feature
  94. if (toSerialize.length) {
  95. if (toSerialize.length === 1) { toSerialize = toSerialize[0]; }
  96. this.val(WktWriter.write(toSerialize));
  97. }
  98. // but clear the value
  99. else {
  100. this.val('');
  101. }
  102. }
  103. // keep only one features for each map input
  104. function limitFeatures (features) {
  105. // copy a list of features
  106. var copyFeatures = features.object.features.slice();
  107. // only keep the last one
  108. var lastFeature = copyFeatures.pop();
  109. // we remove a lot of features, don't trigger events
  110. features.object.destroyFeatures(copyFeatures, {silient: true});
  111. }
  112. if (behavior && !$(context).hasClass('geofield-processed')) {
  113. // we get the .form-item wrapper which is a slibling of our hidden input
  114. var $wkt = $(context).closest('.form-item').parent().find('input.geofield_wkt');
  115. // if there is no form input this shouldn't be activated
  116. if ($wkt.length) {
  117. var dataLayer = new OpenLayers.Layer.Vector(Drupal.t('Feature Layer'), {
  118. projection: dataProjection,
  119. drupalID: 'openlayers_behavior_geofield'
  120. });
  121. dataLayer.styleMap = Drupal.openlayers.getStyleMap(data.map, 'openlayers_behavior_geofield');
  122. data.openlayers.addLayer(dataLayer);
  123. // only one feature on each map register before adding our data
  124. if (Drupal.settings.geofield.data_storage == 'single') {
  125. dataLayer.events.register('featureadded', $wkt, limitFeatures);
  126. }
  127. if ($wkt.val() != '') {
  128. wktFormat = initWktFormat(data.openlayers.projection);
  129. features = wktFormat.read($wkt.val());
  130. dataLayer.addFeatures(features);
  131. }
  132. // registering events late, because adding data
  133. // would result in a reprojection loop
  134. dataLayer.events.register('featureadded', $wkt, updateWKTField);
  135. dataLayer.events.register('featureremoved', $wkt, updateWKTField);
  136. dataLayer.events.register('afterfeaturemodified', $wkt, updateWKTField);
  137. // transform options object to array
  138. behavior.tools = [];
  139. // add a new 'tools' key which is an array of enabled features
  140. $.each(behavior.feature_types, function (key, value) {
  141. if (value) {
  142. behavior.tools.push(key);
  143. }
  144. });
  145. // create toolbar
  146. var control = new OpenLayers.Control.GeofieldEditingToolbar(dataLayer, behavior);
  147. data.openlayers.addControl(control);
  148. // on submit recalculate everything to be up to date
  149. var formData = {
  150. 'control': control,
  151. 'dataLayer': dataLayer
  152. };
  153. function handleSubmit (e) {
  154. $.map(e.data.control.controls, function(c) { c.deactivate(); });
  155. dataLayer.events.triggerEvent('featuremodified');
  156. }
  157. $(context).parents('form').bind('submit', formData, handleSubmit);
  158. }
  159. $(context).addClass('geofield-processed');
  160. } // if
  161. }
  162. };
  163. })(jQuery);