This is a continuation from a previous post regarding manipulation of SVG in a UIWebview. For more background info please see here first: UIWebview manipulating SVG 'on the fly'
Now I am trying to create SVG on the fly within the same frame work.
I have tried using the createElementNS method in Javascript without success.
Here is my failed attempt:
NSString *string = #"var svgDocument=document.getElementById('circle').getSVGDocument();var shape=svgDocument.createElementNS('http://www.w3.org/2000/svg', 'greencircle');shape.setAttributeNS(null, 'cx', 25);shape.setAttributeNS(null, 'cy', 25);shape.setAttributeNS(null, 'r', 20);shape.setAttributeNS(null, 'fill', 'green');svgDocument.appendChild(shape);";
[webView stringByEvaluatingJavaScriptFromString:string];
Could somebody please show me an example of how to create a simple circle with a similar approach as above. Or if there is a better way to create SVG graphics on the fly then I'd love to know!
Thanks.
You're actually pretty much there.
The second argument to createElementNS should be the type of element you're creating (circle) rather than an identifier (greencircle) e.g.
var shape=svgDocument.createElementNS('http://www.w3.org/2000/svg', 'circle');
You can set an id with setAttributeNS instead.
shape.setAttributeNS(null, 'id', 'greencircle');
Also, append to svgDocument.documentElement rather than just svgDocument, otherwise you'll get an error:
svgDocument.documentElement.appendChild(shape);
As an aside if you aren't already the best way to quickly test all this stuff is in Chrome or Safari on your desktop with the developer tools turned on. Makes things much easier to debug.
So if you're working with the files mentioned in the earlier question about manipulating SVG you could prototype with:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SVG</title>
<script>
function make_circle() {
// test new Javascript code here before compacting it
var svgDocument=document.getElementById('circle').getSVGDocument();
var shape=svgDocument.createElementNS('http://www.w3.org/2000/svg', 'circle');
shape.setAttributeNS(null, 'id', 'greencircle');
shape.setAttributeNS(null, 'cx', 25);
shape.setAttributeNS(null, 'cy', 25);
shape.setAttributeNS(null, 'r', 20);
shape.setAttributeNS(null, 'fill', 'green');
svgDocument.documentElement.appendChild(shape);
}
</script>
</head>
<body>
<!-- click on link to test the code -->
<a onclick='make_circle();'>Change color</a>
<object id="circle" data="circle.svg" width="250" height="250" type="image/svg+xml"/>
</body>
</html>
Obviously you can't test any of the touch events this way. :(
In terms of a better way as your Javascript gets more complex it might be worth working out how to keep everything in a separate .js file in your app bundle and then loading it into the webview by creating and inserting a dynamically created tag with stringByEvaluatingJavaScriptFromString.
Related
Is it possible to use relative links in tvml? I've never had a problem using them in a webpage but just can't get it to work in my tvml docs.
From my swift:
static let TVBaseURL = "http://localhost:9001/"
This currently works from my tvml which is located at http://localhost:9001/templates/home.xml
<lockup onselect="getDocument('templates/Featured.xml')">
<img src="http://localhost:9001/graphics/icons/ICON_featured.png" width="313" height="600" />
</lockup>
Note that the onselect link is relative and works fine. However this doesn't work...
<lockup onselect="getDocument('templates/Featured.xml')">
<img src="../graphics/icons/ICON_featured.png" width="313" height="600" />
</lockup>
It all depends on how you define YOUR getDocument function. But from your code, most likely it looks a bit like this one from the official TVML Programming Guide, sec 8-3.
function getDocument(extension) {
var templateXHR = new XMLHttpRequest();
var url = baseURL + extension;
loadingTemplate();
templateXHR.responseType = "document";
templateXHR.addEventListener("load", function() {pushPage(templateXHR.responseXML);}, false);
templateXHR.open("GET", url, true);
templateXHR.send();
}
Which uses a pre-set baseURL like your code does. Thus, your get document support relative links. (and not universal link. putting the full http://localhost:9001/index.xml will break it.)
in this example, the XMLHttpRequest object open function, takes the full url, not the relative one. Read more about XMLHttpRequest open here.
In short. Nothing is relative here.
However, you can do something similar with the power of Javascript.
When you get a hold of the XML document, you can find all the tag with document.getElementsByTagName("img"), which give you a list of the image element. Then all it is left to do it to look at each of them with .item(i), get their source attribute by .getAttribute('src'), see if it start with http or https, and if not, set the new one by .setAttribute('src', baseUrl+imagePath)
How can I generate a map like this using OSM? I want the map to highlight single country and fade others. Also, if the country is small I want to show it on the globe in a small thumbnail.
Oke let’s using JavaScript, because I think there is the biggest variety of libraries. Here I will explain a few approaches creating an interactive webmap.
1) The first approach is using plain svg:
You can download or draw with your vector software of choice the base map as svg. Then you could assign every country polygon a unique ID, and inside JS you can access the SVG with a mouseevent like click or mouseover. All the information of the country could be stored outside JS in a .json (easier) or .xml file. With the ID you getting from the SVG event you can get the fitting information from your .json. Maybe that reinvent the wheel, but it’s highly adjustable. But I think if you only want a static maps its simpler if you are using a more complex library.
2) The second approach is using a library for svg interaction:
The very popular D3.js or Raphael.js
3) The third approach is using a thematic webmapping library based on svg:
Use JQVMAP (former vectormap.js) or the very new austrian project mapmap.js
4) Use a topographic webmapping library
Here you can use the open libraries leaflet.js or openlayers.js. With these, the best approach will be, that you add your countries as a .geojson. Geojson is a very nice format that allows you interacting with your countries with the most geographical softwares.
5) Create und use your own tiles
This approach is the most performant solution but not the simplest to implement.
Here is a very nice tutorial explaining five approaches. But I think the simplest is using TileMill.
6) Using a mapserver
If you are not familiar with mapservers, this should only be considered when you are going to implement an extensive application. Nice Mapservers are Deegree and the popular Geoserver.
All of these approaches have their pros und cons but I think one of these solutions will fit your needs and I wish you the best successes!
You can use google Geo Chart. You can highlight any country you wanted.
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {
'packages':['geomap'],
// Note: you will need to get a mapsApiKey for your project.
// See: https://developers.google.com/chart/interactive/docs/basic_load_libs#load-settings
'mapsApiKey': 'AIzaSyD-9tSrke72PouQMnMX-a7eZSW0jkFMBWY'
});
google.charts.setOnLoadCallback(drawMap);
function drawMap() {
var data = google.visualization.arrayToDataTable([
['Country', 'Popularity'],
['Germany', 200],
['United States', 300],
['Brazil', 400],
['Canada', 500],
['France', 600],
['RU', 700]
]);
var options = {};
options['dataMode'] = 'regions';
var container = document.getElementById('regions_div');
var geomap = new google.visualization.GeoMap(container);
geomap.draw(data, options);
};
</script>
</head>
<body>
<div id="regions_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
For more info here is the link
https://developers.google.com/chart/interactive/docs/gallery/geomap?csw=1
I am working on a project in Zend Framework 1.12. I want to build a facility that will enable members to dynamically upload a VCSS stylesheet of their choice; thus enabling them to format the page in the colour of their choice. The parameters to their stylesheet is load via the URL;
i.e
The url could be like this: samplewebbsite/?s=rootfolder/stylesheet
we collect it with: $this->view->stylesheet = $this->_request->getParam('stylesheet', ' );
The getParam() gets the distination to their style sheet. i.e: rootfolder/stylsheet.css
I then display the value on the index page i.e:
<link href="<?= $this->stylesheet ?>" media="screen" rel="stylesheet" type="text/css" >
My question now is this: I want to protect the getParam() from javascript/sql injection/bad code etc. How do I protect it? Should I use strip_tags() or is there a better way to protect it?
i think i worked out how to do it; i did this; i simply used strip tags.
$this->view->stylesheet = $stylesheet = strip_tags ($this->_request->getParam('s', ''));
i tried to use the
$alpha = new Zend_Filter_Alpha();
$this->view->stylesheet = $alpha -> filter($this -> _request -> getParam('name'));
But i found that it was also taking out all the break lines i.e the http /:Sameplesite/Rootfolder/ became samplesiteRootfolder
if anyone has a better solution, i would be keen to hear ( ie i would have preferred to use the filter class). but otherwise. i think that my question is pretty much answered.
I'm using the IE8 debugger to fix a script that works great in FF 3.16 and Chrome 12.0, but doesn't work for beans in IE 8.0 or Safari 5.0. The spot in the script that's giving me trouble is here:
I need to find the number of <td>s in the the table id="main_tbody" whose children[0] is the first row of data. Both FF and Chrome understand this perfectly; IE 8 and Safari 5 do not.
I want to look at the DOM tree in the IE 8 debugger to see what's going on. But I can't find the ding-dong DOM, dang it!
So: where is the DOM in the IE 8 debugger?
Alternatively <ahem!>: what's wrong with my JS code?
Thanks!
EDIT: I should have said that the table is set up like this:
<table id ="main">
<tbody id="main_tbody">
And references to table id ="main" and tbody id="main_tbody" are initialized this way:
main = getRefToDiv( 'main' );
main_tbody = getRefToDiv( 'main_tbody' );
Call the position_col_heads() function after your </body>
My suspicion is that this function is declared inside the head tag or being called before the browser renders the body content.
Just try this.
...
...
</body>
<script type='text/javascript'>
position_col_heads();//Set breakpoint here and see if its accessible.
</script>
</html>
Also, see what response you get for main.children[0] and main_tbody.innerHTML in your watch expression.
Unbelievable. According to quirksmode, ie8 fails to implement childElementCount and I believe it because that's the thing that's coming back == 'undefined'. So I'll rewrite my loop with a new exit condition. That sucks, because now I'm going to get all children, including comments and everything else, not just the elements I was looking for. Incredible. FYI, ie8 also does not implement firstElementChild, lastElementChild, nextElementSibling, or previousElementSibling.
I have a couple of gists which I need to include in a website post to showcase the source code. Currently, I'm inlining each of the multiple gists at various places in the HTML with script tags, however, this would be a blocking call. So, is there a way to dynamically load the gists and paste it specific points in time.
I tried something like below :-
<html>
<body>
<div id="bookmarklet_1.js"></div>
<div id="bookmarklet_2.js"></div>
<div id="bookmarklet_3.js"></div>
var scriptMap = {'bookmarklet_1.js' : 'https://gist.github.com/892232.js?file=bookmarklet_1.js',
'bookmarklet_2.js' : 'https://gist.github.com/892234.js?file=bookmarklet_2.js',
'bookmarklet_3.js' : 'https://gist.github.com/892236.js?file=bookmarklet_3.js'};
var s, scr, holder;
for(s in scriptMap){
holder = document.getElementById(s);
scr= document.createElement('script');
scr.type= 'text/javascript';
scr.src= scriptMap[s];
holder.appendChild(scr);
}
</script>
</body>
</html>
The above didn't work for me, it seems that each script is doing a document.write internally to write the CSS and soure code. Has anyone tried this before or got it working ?
I started a project exactly for this purpose. Dynamically-embedded Gists
Try it now: http://urlspoiler.herokuapp.com/gists?id=992729
Use the above url as the src of a dynamically-created iframe, or add &format=html to get the Gist html snippet via ajax, then put it anywhere you want. (The gist in the above url also happens to be the documentation for how to use this project.)
I myself wanted to do exactly the same thing (with the addition of even removing the default gist style link) - ended up building a "generic" script loader that handles document.write calls :
https://github.com/kares/script.js
Here's how one can use it for embedding gists (and pasties) :
https://github.com/kares/script.js/blob/master/examples/gistsAndPasties.html
You can now get the HTML + CSS directly using JSONP.
I wrote a fuller answer in response to this question, but the key is that you can get the HTML + CSS using JSONP.
For example: https://gist.github.com/anonymous/5446989.json?callback=callback12345
callback12345({
"description": "Function to load a Gist without an iframe",
"public": true,
...
"div": <HTML code>,
"stylesheet": <URL of CSS file>
})