Adding and removing markers in openlayers on Drupal after page-load - drupal

I have to change the data set displayed on a map according to selections on the page and I would like to do this by creating several marker layers then switching between them based on user input.
For some reason I cannot add a layer after the map has been rendered on the page, seems like it shouldn't be that hard I think I may have the syntax wrong since the way Drupal sets up the map is different from straight forward openlayers.
Can I not get the map object like
var map = Drupal.settings.openlayers.maps["openlayers-map-auto-id-0"];
then add and remove marker layers from it? maybe there's another way of getting it?
Any help appreciated,
- Chris

The Drupal OpenLayers module only stores settings in Drupal.settings.openlayers.maps.
What you need is something like this:
var ol = $('#openlayers-map-auto-id-0').data('openlayers');
var max_extent = ol.openlayers.getMaxExtent(); // Or some other OpenLayers method...
...
The actual OpenLayers instance (as well as a copy of the map-specific settings) are stored with jQuery's .data() method. When you call $('#map-id').data('openlayers') you'll get back an object with map and openlayers members that correspond to the map settings and the actual OL object instance, respectively.
You might want to consider writing an OL behavior to handle your use case -- check out the default behaviors provided by the Drupal OpenLayers module to get a sense of how this works.

Related

How can i reCalculate route on waypoint change?

I'm using JS api. I need to recalculate route if waypoint is changed (via input field or waypoint marker is dragged).
As i understand, we can't recalculate existing route, so we need to destroy the previous one and to make the new one?
So how should i destroy the existing one as i have only "routes" object available inside the addWaypointsToMap function?
Well, i resolved it.
The moment route is changed (waypoint dragged or relocated) i check if map groups for polygon and waypoints markers exist and kill'em, then make new route.
Not sure what does exactly "recalculate existing route" means, but if it means to update Polyline map object based on new routing response then you can simply use
H.map.Polyline#setGeometry()
The method is documented here: https://developer.here.com/documentation/maps/3.1.16.1/api_reference/H.map.Polyline.html#setGeometry
Here is a simple jsfiddle example to set start & destination (as well as middle waypoint) point by mouse right-click and re-calculate the route.

Algolia - WordPress - how can I get the actual query into JS variable to work with it further in the hits template?

I would like to do some interesting stuff with the hits that are being displayed based on the search query that user is not only typing into search box but actually filtering using the instant search filters. I have filter based on hierarchical events_location taxonomy. Based on what user selected I would get the info in JS variable that I can then further use to do other operations in the hits div, specifically on each hit card.
So my URL when searching updates like this:
/what-to-see/?q=&idx=sdbeta_posts_events&p=0&hFR%5Btaxonomies_hierarchical.events_calendar.lvl0%5D%5B0%5D=JUL%204&hFR%5Btaxonomies_hierarchical.events_category.lvl0%5D%5B0%5D=All&hFR%5Btaxonomies_hierarchical.events_locations.lvl0%5D%5B0%5D=Paddock%20Stage
I could potentially take the URL and extract the data from it, but I am sure there is more elegant way of working with the query.
In InstantSearch.js, the state is managed by another library called the algoliasearch-helper. Through this library you can read and write the search parameters.
The cleanest to access the helper is to build a custom widget, which is a plain object with lifecycle hooks (initial rendering and the other renderings). You can read more about custom widgets there.
Once you've accessed the helper, you can read and write with the helper API.
This can be found under search.searchParameters
So:
console.log(search.searchParameters);
Will give you whole object that you can then work with.
There is however one issue with this and that is that it works only on initial load. I was unable to make this work or get any data after starting to selecting categories. So if anyone knows how to use this so it updates after each selection please comment bellow.

Mixing Google Maps custom overlays with Backbone Views

TL;DR
Is PinView.prototype = _.extend(PinView.prototype, google.maps.OverlayView.prototype) the "proper" way to have a Backbone View inherit from another "class"?
Long read
We're redoing our site using Backbone and are working on including some mapping functionality.
I've got a Backbone view that handles placing <div>s onto specific points within the browser window; this seems like a natural thing to extend in order have Google's Map API place them on geographical coordinates.
According to the Google API, in order to generate a custom overlay you create a new object and set the prototype for that object to a new instance of google.maps.OverlayView. You then implement three functions on top of that object so that the object responds to:
onAdd
draw
onRemove
Where onAdd is responsible for generating the HTML and then applying it on top of the Map. This subsequently calls draw which positions the element correctly according to the LatLng pairs and bounds you've provided. onRemove gets called when you want to get rid of your layer.
So I've modified my View to include these three methods (which just call render and unrender and are bound to my collection). And then to make "the magic happen" I'm doing:
PinView.prototype = _.extend(PinView.prototype, google.maps.OverlayView.prototype)
Does this look right? I can post the code for the View and the Model on which it's based, but honestly, they're irrelevant to this example -- the code works and I'm able to place custom divs generated through Backbone model, view and controller components on the map without a issue, what I'm asking I guess (and maybe this question is more apropos for programmers.se, so let me know and I'll move it).
This seems to be the easiest way to make my PinView both a Backbone View and a Google Maps OverlayView, but I'm not 100% comfortable with prototypal inheritance to know if I'm doing something "wrong" or breaking something somewhere down the road.
Nice idea! I'm usually a bit sceptical about weather or not you're 'correct' when things work so if you haven't run into a showstopper and the overlays shows up and does what the're supposed to do I'd say you are.
One thing to check out closer, though:
This isn't (and can't) be "real" multiple inheritance - that concept isn't really relevant in a prototype based language: one implementation of a method will inevitable "win" and overwrite the other implementation, at least when using _.extend()
This means that if there are members or methods with the same names in Backbone.View and google.maps.OverlayView the one last in your _.extend() call will be the one that takes over. But when I inspect them using Chrome's Developer Tools I didn't see any obvious collision of this kind.
So my recommendation: continue using this, just test a lot. I'd love to see an example of this technique some time.
Ah! So I've been doing the above, but it's never felt right.
Then I found this discussion on a Backbone group which leads me to the following:
var MyView = (function(){
var view = function(){
Backbone.View.apply(this, arguments);
};
view.extend = Backbone.View.extend;
_.extend(view.prototype, Backbone.View.prototype, google.maps.OverlayView.prototype, [other prototypes...], { [VIEW DEFINITION] });
return view;
}());
This way if we need to override any of the definitions in a class we're extending from, we can since it's earlier in the _.extend chain (later definitions overwrite earlier definitions).
I'm working on 'extending' extend to keep track of the "parent" object's references that would be overridden and providing a method to call them still (like Python's super call). I haven't decided if this should be done through monkey-patching, an intercepter pattern (via underscore's _.tap() method or something else, but I think it'll add a lot of flexibility.
This would allow you to define an initialize view in your "parent" class which could be called by doing something like _.super('ParentClass', 'initialize'); at the end of the "child" class's initialize routine...

Flex, filter tree using ITreeDataDescriptor without reload and close all nodes

working with flex 4 and implementing filtering using ITreeDataDescriptor.
Filtering worked as expected like the following code snippet
however, i am trying to create a on-demand type of filter where user would type in the search clause in a TextInput, and as the user types, the tree nodes would be filtered on the fly.
my implementation now is have user click on the search button and then reapply the dataDescriptor then reload the data. A big problem is that the whole tree collapses after setting the dataProvider again.
any suggestion on how the on-demand filter can be achieved?
var dataFilter:ServicePricingFilter = new MyFilter();
dataFilter.searchString = this.txtSearchKeyword.text;
this.treeService.dataDescriptor = new MyDataDescriptor(dataFilter);
this.treeService.dataProvider = getTreeData();
I think you shouldn't set the dataprovider every time but use insted the filterFunction property available for ListCollectionView classes (ArrayCollection, XMLListCollection,...)
looked at the post Florian mentioned.
on-demand filtering is done by using ITreeDataDescriptor and a filterFunction.
on keyup event of the search TextInput, call invalidateList() function on the tree.
see the source code provided for the following post
http://www.davidarno.org/2009/04/01/how-to-filter-all-nodes-of-a-flex-tree-component/

Panel page URL - Need to access named arguments

I have a Panel page, which I have given a path of: books/travel-books/%city/%country/%page. The help text underneath the field says "The URL path to get to this page. You may create named placeholders for variable parts of the path by using %name for required elements and !name for optional elements. For example: "node/%node/foo", "forum/%forum" or "dashboard/!input". These named placeholders can be turned into contexts on the arguments form.", so I have named my arguments appropriately.
So now in my code, I need to get the values of those arguments. I've seen arg(0), but that requires me knowing which index the argument has. Is there anyway to access it by the name I gave it in the path? Something like arg('city')??
The reason being, that I need to have similar path arguments on many pages, and need to access the values of these in my module. But the arguments may be in different places for another page. For instance, another page might be at: flights/%city/%country. Then I want to access the city argument within the same function, but it is at a different index.
Can anyone help?
you can check for arg(0) first, see whether it is 'books', 'flights', whatever... then associate names accordingly. do it as a helper function in a custom module and call it before referencing (wherever you're referencing it).
The text that you quoted from the panels help text is referring to what panels call context.
Panels
Panels has a great use if you want to aware of what context a certain piece of content is being viewed. Fx if you had several shops with different products, you might want to control which blocks in a sidebar would be displayed, based on the shop that the product belonged to.
This is essential what context is in panels and what the named placeholdes are used for. You can be default add different kinds of context, fx nodes, users, taxonomy terms. You can then use the different pieces of context if various ways.
If panels default options is not enough, you can also create your own plugins to panels to make it handle your special cases. But it requires a lot of time to learn how panels work.
Other solutions
Using panels might not be the easiest option for you, it depends what you are aiming for. But if you don't need to make pages that is aware of the context, this would probably be a lot easier to do with views and theming. Views can handle arguments in urls very well, and it is a lot simpler to both style and configure.
In Drupal 7 you can get the arguments from hook_content_type_render
function <your plugin name>_content_type_render($subtype, $conf, $panel_args, $context) {
$block = new StdClass;
$block->title = t('test');
$block->content = 'test panel arg: '.$panel_args[0];
return $block;
}
Custom panel tutorial

Resources