svg.js with existing svg - svg

I'm trying to implement svg.js to make a map of a clickable floorplan.
But I cannot make this work properly, or this works but doesn't work like I expected:
const map = SVG.get('mysvg');
map.click(function( event ) {
this.fill({ color: '#000' });
console.log(this);
console.log(event.target);
});
When I try to click on some area on the map, instead of change fill color I get nothing.
Actually svgjs triggers 'create' as you can see in console with inspector.
Not sure what am I doing wrong here?
I would expect that the area will change fill color?
https://codepen.io/bobz-zg/pen/LdyXBe

You can use the select function as described here to create a Set. You'd then use the each() method from Set to iterate over each entry and apply the click event handler. For example:
const map = SVG.get("mysvg");
var restaurants = map.select('[id*="restaurant"]:not(g)'); // Create an svg.js Set, but do not capture the group in the set
restaurants.each(function() {
this.click(function(event) {
this.fill({ color: "#000" });
});
});
If you can edit the svg that you are using as an input, I would suggest adding a class to each of the clickable elements to use that as the reference for select. Otherwise, you'll have to do something like selecting all element id 'types' (i.e. restaurant, retail etc.) separately and concatenating the Sets using Set.add() before you do the loop to add the click listener, but that could get messy.

Related

MDC-Web: Multiple simple menu

I use google MATERIAL COMPONENTS FOR THE WEB and have problems with the "Simple Menu". Check my codepen: [Multiple menus per page?][1]
[1]: https://codepen.io/QJan84/pen/govRmg
The first menu works, the others do not.
What do I have to do to have multiple menus per page?
You’re using document.querySelector for menu and toggle, but it will return only the first node elements matching “.mdc-simple-menu” and “.js--toggle-dropdown” respectively.
Instead, you should use document.querySelectorAll that will return the NodeList, which you’ll need to convert to array to iterate with its elements.
I wrapped your example menus and toggles into containers for selecting toggles easier with Node.parentElement.
So, the final result might look like this:
const menuEls = Array.from(document.querySelectorAll('.mdc-simple-menu'));
menuEls.forEach((menuEl) => {
// Initialize MDCSimpleMenu on each ".mdc-simple-menu"
const menu = new mdc.menu.MDCSimpleMenu(menuEl);
// We wrapped menu and toggle into containers for easier selecting the toggles
const dropdownToggle = menuEl.parentElement.querySelector('.js--dropdown-toggle');
dropdownToggle.addEventListener('click', () => {
menu.open = !menu.open;
});
});
You can view the demo on Codepen.

How to add an absolute element in a NativeScript page

I want to be able to just place a View component (plugin) into the page through code and have it appear at some X\Y on the page... but I'm a bit stumped.
Any attempt to add via page.content kinda adds it to the layout\render pass so it occupies space.
So this would get injected into "any" page at "any" time, I have no control over the markup this would be used in (know what I mean?) There is no XML for it and unfortunately the answer can't just be wrap everything in an AbsoluteLayout because one can't mandate that on users apps\layouts.
Thoughts, even possible?
Basically the simplest way to do this is to dynamically and be fully cross platform compatible is to create a AbsoluteLayout item in your JavaScript code, and dynamically insert your item and the AL into the page container.
Code would be something like this:
var AbsoluteLayout = require('ui/layouts/absolute-layout').AbsoluteLayout;
var myAL = new AbsoluteLayout();
var myItem = new myPluginItem();
// Set you left, right, top, bottom coords.
myItem.top = x;
// Add our item to the AbsoluteItem
myAL.addChild(myItem);
var frame = require('ui/frame');
var page = frame.topmost().currentPage;
var LayoutBase = require('ui/layouts/layout-base').LayoutBase;
page._eachChildView(function(view) {
if (view instanceof LayoutBase) {
view.addChild(myAL);
return false;
}
return true;
});
However, if you don't want to do this the really simple way; the only other way is to actually go a bit lower level. You can natively access the iOS view controller (page._ios.view) and the android view (page._nativeView), and then manually add it to the view by using things like addView (https://developer.android.com/reference/android/view/ViewManager.html) or addSubview (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/).
I would like to add you can set the Top and Left properties in TypeScript by importing AbsoluteLayout like so
import {AbsoluteLayout} from 'ui/layouts/absolute-layout';
and then using the exposed functions setLeft or setTop
AbsoluteLayout.setLeft(YourItem, LeftValue);
or
AbsoluteLayout.setTop(YourItem, TopValue);

How can you control visibility of datasource in Cesiumjs?

I want to display multiple datasources in a cesiumjs viewer but need to allow the user to select which ones they want to see at any given time. For example, if I load a kml and a czml file, how do I hide one and show the other? I can't find the cesiumjs way to do this with its API.
Update Feb 2016: A show flag has been proposed and may be added to a future version of Cesium.
Original answer:
Currently there is no show flag on the dataSource, however it is easy to add and remove the dataSource from the list of available dataSources, and this is used to get the show/hide functionality.
Here's a working demo: Load the Cesium Sandcastle Hello World example, and paste the following code into the left side, then hit Run (F8). It should display a checkbox in the upper-left with show/hide functionality.
var viewer = new Cesium.Viewer('cesiumContainer');
// Create a typical CzmlDataSource.
var dataSource1 = new Cesium.CzmlDataSource();
dataSource1.load('../../SampleData/simple.czml');
// Add a checkbox at the top.
document.getElementById('toolbar').innerHTML =
'<label><input type="checkbox" id="showCheckbox" /> Show CZML</label>';
var checkbox = document.getElementById('showCheckbox');
checkbox.addEventListener('change', function() {
// Checkbox state changed.
if (checkbox.checked) {
// Show if not shown.
if (!viewer.dataSources.contains(dataSource1)) {
viewer.dataSources.add(dataSource1);
}
} else {
// Hide if currently shown.
if (viewer.dataSources.contains(dataSource1)) {
viewer.dataSources.remove(dataSource1);
}
}
}, false);
This code could be improved, for example it could be a "lazy load" where the dataSource.load does not get called until the first time it's shown. Also if a dataSource has been hidden a while, you have to consider at what point should you be saving memory by destroying the dataSource rather than continuing to hold onto it (triggering a new lazy load if it is later shown again).
as of now, show is a property of the data source, you can control it by accessing the property in dot or bracket notation:
https://cesiumjs.org/Cesium/Build/Documentation/CzmlDataSource.html#show
const src = new Cesium.CzmlDataSource();
src.show = false;

Highlighting or Bolding the Borders of a kml Polygon

Hey after loading a kml file to google earth I was trying to have when a user clicks a certain polygon from the kml, to have that polygon highlighted.
So far I can record the click event, get the event type (KmlPlacemark) and grab its kml markup.
I tried doing something similar to this example where they add a placemark to the getFeatures of the kmlObject but both target and type don't seem to have 'getFeatures'. After looking around the documentation I think I might either want setOutline from Kml Polystyle class or setWidth() from KmlLineStyle class but am not sure. Also when I try something like target.setOutline(true); it doesn't work.
Can anyone tell me if I'm on the right track, hints to what I'm doing wrong, and if there's a better way to do this?
function recordEvent(event) {
var target = event.getTarget();
var type = target.getType();
if(type == "KmlPolygon") {
alert("KMLPolygon ");
}else if(type == "KmlPlacemark") {
// // get the data you want from the target.
var description = target.getDescription();
var balloon = target.getBalloonHtml();
var outputKml = target.getKml();
if ('getFeatures' in event) {
console.log("test");
event.getFeatures().appendChild(placemark);
}
console.log("hello?")
// target.setOutline(true);
console.log(outputKml);
}
};
google.earth.addEventListener(ge.getGlobe(), 'click', recordEvent);
Thanks!
I find the best way to do what you are asking is to:
Detect click events like you currently do
If clicked, create a new Style, then assign it to the target
var newStyle = ge.createStyle('');
// Assign your Style's attributes such as LabelStyle and IconStyle
// eg to set the scale of your label
newStyle.getLabelStyle().setScale(2.5);
// Set the Style
target.setStyleSelector(newStyle);
Edit to add in this link of a Google example showing it more in depth
https://code.google.com/apis/ajax/playground/#styling_placemarks_using_style_maps

how to get window width and height with YUI?

How do I get those values? I see the example on the YUI page to do this but using a click event, and then calling the get('winWidth') method on the event target. But how can I get these values without the use of any event? Thanks
Simply
YAHOO.util.Dom.getViewportWidth();
YAHOO.util.Dom.getViewportHeight();
keep in mind you can reduce YUI namespace as shown bellow
(function() {
var Yutil = YAHOO.util,
Ydom = Ytil.Dom;
Ydom.getViewportWidth();
Ydom.getViewportHeight();
})();

Resources