Panel.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
  2. * full list of contributors). Published under the Clear BSD license.
  3. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
  4. * full text of the license. */
  5. /**
  6. * @requires OpenLayers/Control.js
  7. */
  8. /**
  9. * Class: OpenLayers.Control.Panel
  10. * The Panel control is a container for other controls. With it toolbars
  11. * may be composed.
  12. *
  13. * Inherits from:
  14. * - <OpenLayers.Control>
  15. */
  16. OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, {
  17. /**
  18. * Property: controls
  19. * {Array(<OpenLayers.Control>)}
  20. */
  21. controls: null,
  22. /**
  23. * APIProperty: autoActivate
  24. * {Boolean} Activate the control when it is added to a map. Default is
  25. * true.
  26. */
  27. autoActivate: true,
  28. /**
  29. * APIProperty: defaultControl
  30. * {<OpenLayers.Control>} The control which is activated when the control is
  31. * activated (turned on), which also happens at instantiation.
  32. * If <saveState> is true, <defaultControl> will be nullified after the
  33. * first activation of the panel.
  34. */
  35. defaultControl: null,
  36. /**
  37. * APIProperty: saveState
  38. * {Boolean} If set to true, the active state of this panel's controls will
  39. * be stored on panel deactivation, and restored on reactivation. Default
  40. * is false.
  41. */
  42. saveState: false,
  43. /**
  44. * APIProperty: allowDepress
  45. * {Boolean} If is true the <OpenLayers.Control.TYPE_TOOL> controls can
  46. * be deactivated by clicking the icon that represents them. Default
  47. * is false.
  48. */
  49. allowDepress: false,
  50. /**
  51. * Property: activeState
  52. * {Object} stores the active state of this panel's controls.
  53. */
  54. activeState: null,
  55. /**
  56. * Constructor: OpenLayers.Control.Panel
  57. * Create a new control panel.
  58. *
  59. * Each control in the panel is represented by an icon. When clicking
  60. * on an icon, the <activateControl> method is called.
  61. *
  62. * Specific properties for controls on a panel:
  63. * type - {Number} One of <OpenLayers.Control.TYPE_TOOL>,
  64. * <OpenLayers.Control.TYPE_TOGGLE>, <OpenLayers.Control.TYPE_BUTTON>.
  65. * If not provided, <OpenLayers.Control.TYPE_TOOL> is assumed.
  66. * title - {string} Text displayed when mouse is over the icon that
  67. * represents the control.
  68. *
  69. * The <OpenLayers.Control.type> of a control determines the behavior when
  70. * clicking its icon:
  71. * <OpenLayers.Control.TYPE_TOOL> - The control is activated and other
  72. * controls of this type in the same panel are deactivated. This is
  73. * the default type.
  74. * <OpenLayers.Control.TYPE_TOGGLE> - The active state of the control is
  75. * toggled.
  76. * <OpenLayers.Control.TYPE_BUTTON> - The
  77. * <OpenLayers.Control.Button.trigger> method of the control is called,
  78. * but its active state is not changed.
  79. *
  80. * If a control is <OpenLayers.Control.active>, it will be drawn with the
  81. * olControl[Name]ItemActive class, otherwise with the
  82. * olControl[Name]ItemInactive class.
  83. *
  84. * Parameters:
  85. * options - {Object} An optional object whose properties will be used
  86. * to extend the control.
  87. */
  88. initialize: function(options) {
  89. OpenLayers.Control.prototype.initialize.apply(this, [options]);
  90. this.controls = [];
  91. this.activeState = {};
  92. },
  93. /**
  94. * APIMethod: destroy
  95. */
  96. destroy: function() {
  97. OpenLayers.Control.prototype.destroy.apply(this, arguments);
  98. for (var ctl, i = this.controls.length - 1; i >= 0; i--) {
  99. ctl = this.controls[i];
  100. if (ctl.events) {
  101. ctl.events.un({
  102. activate: this.iconOn,
  103. deactivate: this.iconOff
  104. });
  105. }
  106. OpenLayers.Event.stopObservingElement(ctl.panel_div);
  107. ctl.panel_div = null;
  108. }
  109. this.activeState = null;
  110. },
  111. /**
  112. * APIMethod: activate
  113. */
  114. activate: function() {
  115. if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
  116. var control;
  117. for (var i=0, len=this.controls.length; i<len; i++) {
  118. control = this.controls[i];
  119. if (control === this.defaultControl ||
  120. (this.saveState && this.activeState[control.id])) {
  121. control.activate();
  122. }
  123. }
  124. if (this.saveState === true) {
  125. this.defaultControl = null;
  126. }
  127. this.redraw();
  128. return true;
  129. } else {
  130. return false;
  131. }
  132. },
  133. /**
  134. * APIMethod: deactivate
  135. */
  136. deactivate: function() {
  137. if (OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
  138. var control;
  139. for (var i=0, len=this.controls.length; i<len; i++) {
  140. control = this.controls[i];
  141. this.activeState[control.id] = control.deactivate();
  142. }
  143. this.redraw();
  144. return true;
  145. } else {
  146. return false;
  147. }
  148. },
  149. /**
  150. * Method: draw
  151. *
  152. * Returns:
  153. * {DOMElement}
  154. */
  155. draw: function() {
  156. OpenLayers.Control.prototype.draw.apply(this, arguments);
  157. this.addControlsToMap(this.controls);
  158. return this.div;
  159. },
  160. /**
  161. * Method: redraw
  162. */
  163. redraw: function() {
  164. for (var l=this.div.childNodes.length, i=l-1; i>=0; i--) {
  165. this.div.removeChild(this.div.childNodes[i]);
  166. }
  167. this.div.innerHTML = "";
  168. if (this.active) {
  169. for (var i=0, len=this.controls.length; i<len; i++) {
  170. this.div.appendChild(this.controls[i].panel_div);
  171. }
  172. }
  173. },
  174. /**
  175. * APIMethod: activateControl
  176. * This method is called when the user click on the icon representing a
  177. * control in the panel.
  178. *
  179. * Parameters:
  180. * control - {<OpenLayers.Control>}
  181. */
  182. activateControl: function (control) {
  183. if (!this.active) { return false; }
  184. if (control.type == OpenLayers.Control.TYPE_BUTTON) {
  185. control.trigger();
  186. return;
  187. }
  188. if (control.type == OpenLayers.Control.TYPE_TOGGLE) {
  189. if (control.active) {
  190. control.deactivate();
  191. } else {
  192. control.activate();
  193. }
  194. return;
  195. }
  196. if (this.allowDepress && control.active) {
  197. control.deactivate();
  198. } else {
  199. var c;
  200. for (var i=0, len=this.controls.length; i<len; i++) {
  201. c = this.controls[i];
  202. if (c != control &&
  203. (c.type === OpenLayers.Control.TYPE_TOOL || c.type == null)) {
  204. c.deactivate();
  205. }
  206. }
  207. control.activate();
  208. }
  209. },
  210. /**
  211. * APIMethod: addControls
  212. * To build a toolbar, you add a set of controls to it. addControls
  213. * lets you add a single control or a list of controls to the
  214. * Control Panel.
  215. *
  216. * Parameters:
  217. * controls - {<OpenLayers.Control>} Controls to add in the panel.
  218. */
  219. addControls: function(controls) {
  220. if (!(OpenLayers.Util.isArray(controls))) {
  221. controls = [controls];
  222. }
  223. this.controls = this.controls.concat(controls);
  224. // Give each control a panel_div which will be used later.
  225. // Access to this div is via the panel_div attribute of the
  226. // control added to the panel.
  227. // Also, stop mousedowns and clicks, but don't stop mouseup,
  228. // since they need to pass through.
  229. for (var i=0, len=controls.length; i<len; i++) {
  230. var element = document.createElement("div");
  231. element.className = controls[i].displayClass + "ItemInactive";
  232. controls[i].panel_div = element;
  233. if (controls[i].title != "") {
  234. controls[i].panel_div.title = controls[i].title;
  235. }
  236. OpenLayers.Event.observe(controls[i].panel_div, "click",
  237. OpenLayers.Function.bind(this.onClick, this, controls[i]));
  238. OpenLayers.Event.observe(controls[i].panel_div, "dblclick",
  239. OpenLayers.Function.bind(this.onDoubleClick, this, controls[i]));
  240. OpenLayers.Event.observe(controls[i].panel_div, "mousedown",
  241. OpenLayers.Function.bindAsEventListener(OpenLayers.Event.stop));
  242. }
  243. if (this.map) { // map.addControl() has already been called on the panel
  244. this.addControlsToMap(controls);
  245. this.redraw();
  246. }
  247. },
  248. /**
  249. * Method: addControlsToMap
  250. * Only for internal use in draw() and addControls() methods.
  251. *
  252. * Parameters:
  253. * controls - {Array(<OpenLayers.Control>)} Controls to add into map.
  254. */
  255. addControlsToMap: function (controls) {
  256. var control;
  257. for (var i=0, len=controls.length; i<len; i++) {
  258. control = controls[i];
  259. if (control.autoActivate === true) {
  260. control.autoActivate = false;
  261. this.map.addControl(control);
  262. control.autoActivate = true;
  263. } else {
  264. this.map.addControl(control);
  265. control.deactivate();
  266. }
  267. control.events.on({
  268. activate: this.iconOn,
  269. deactivate: this.iconOff
  270. });
  271. }
  272. },
  273. /**
  274. * Method: iconOn
  275. * Internal use, for use only with "controls[i].events.on/un".
  276. */
  277. iconOn: function() {
  278. var d = this.panel_div; // "this" refers to a control on panel!
  279. d.className = d.className.replace(/ItemInactive$/, "ItemActive");
  280. },
  281. /**
  282. * Method: iconOff
  283. * Internal use, for use only with "controls[i].events.on/un".
  284. */
  285. iconOff: function() {
  286. var d = this.panel_div; // "this" refers to a control on panel!
  287. d.className = d.className.replace(/ItemActive$/, "ItemInactive");
  288. },
  289. /**
  290. * Method: onClick
  291. */
  292. onClick: function (ctrl, evt) {
  293. OpenLayers.Event.stop(evt ? evt : window.event);
  294. this.activateControl(ctrl);
  295. },
  296. /**
  297. * Method: onDoubleClick
  298. */
  299. onDoubleClick: function(ctrl, evt) {
  300. OpenLayers.Event.stop(evt ? evt : window.event);
  301. },
  302. /**
  303. * APIMethod: getControlsBy
  304. * Get a list of controls with properties matching the given criteria.
  305. *
  306. * Parameter:
  307. * property - {String} A control property to be matched.
  308. * match - {String | Object} A string to match. Can also be a regular
  309. * expression literal or object. In addition, it can be any object
  310. * with a method named test. For reqular expressions or other, if
  311. * match.test(control[property]) evaluates to true, the control will be
  312. * included in the array returned. If no controls are found, an empty
  313. * array is returned.
  314. *
  315. * Returns:
  316. * {Array(<OpenLayers.Control>)} A list of controls matching the given criteria.
  317. * An empty array is returned if no matches are found.
  318. */
  319. getControlsBy: function(property, match) {
  320. var test = (typeof match.test == "function");
  321. var found = OpenLayers.Array.filter(this.controls, function(item) {
  322. return item[property] == match || (test && match.test(item[property]));
  323. });
  324. return found;
  325. },
  326. /**
  327. * APIMethod: getControlsByName
  328. * Get a list of contorls with names matching the given name.
  329. *
  330. * Parameter:
  331. * match - {String | Object} A control name. The name can also be a regular
  332. * expression literal or object. In addition, it can be any object
  333. * with a method named test. For reqular expressions or other, if
  334. * name.test(control.name) evaluates to true, the control will be included
  335. * in the list of controls returned. If no controls are found, an empty
  336. * array is returned.
  337. *
  338. * Returns:
  339. * {Array(<OpenLayers.Control>)} A list of controls matching the given name.
  340. * An empty array is returned if no matches are found.
  341. */
  342. getControlsByName: function(match) {
  343. return this.getControlsBy("name", match);
  344. },
  345. /**
  346. * APIMethod: getControlsByClass
  347. * Get a list of controls of a given type (CLASS_NAME).
  348. *
  349. * Parameter:
  350. * match - {String | Object} A control class name. The type can also be a
  351. * regular expression literal or object. In addition, it can be any
  352. * object with a method named test. For reqular expressions or other,
  353. * if type.test(control.CLASS_NAME) evaluates to true, the control will
  354. * be included in the list of controls returned. If no controls are
  355. * found, an empty array is returned.
  356. *
  357. * Returns:
  358. * {Array(<OpenLayers.Control>)} A list of controls matching the given type.
  359. * An empty array is returned if no matches are found.
  360. */
  361. getControlsByClass: function(match) {
  362. return this.getControlsBy("CLASS_NAME", match);
  363. },
  364. CLASS_NAME: "OpenLayers.Control.Panel"
  365. });