Slippy maps for gmaps4rails - ruby-on-rails-3

I thought it would be nice to use OpenStreetMap (or OpenCycleMap) as a map tile provider within the google API. Here is an example of how this is done in plain javascript:
<script type="text/javascript">
var element = document.getElementById("map");
/*
Build list of map types.
You can also use var mapTypeIds = ["roadmap", "satellite", "hybrid", "terrain", "OSM"]
but static lists sucks when google updates the default list of map types.
*/
var mapTypeIds = [];
for(var type in google.maps.MapTypeId) {
mapTypeIds.push(google.maps.MapTypeId[type]);
}
mapTypeIds.push("OSM");
var map = new google.maps.Map(element, {
center: new google.maps.LatLng(48.1391265, 11.580186300000037),
zoom: 11,
mapTypeId: "OSM",
mapTypeControlOptions: {
mapTypeIds: mapTypeIds
}
});
map.mapTypes.set("OSM", new google.maps.ImageMapType({
getTileUrl: function(coord, zoom) {
return "http://tile.openstreetmap.org/" + zoom + "/" + coord.x + "/" + coord.y + ".png";
},
tileSize: new google.maps.Size(256, 256),
name: "OpenStreetMap",
maxZoom: 18
}));
</script>
http://wiki.openstreetmap.org/wiki/Google_Maps_Example
This way one could have an OSM map (which looks a lot nicer for example for hiking or cycling purposes) combined with the google map types and the much nicer google interface, plus all of the methods and options that are only available for google maps in gmaps4rails (eg. clustering etc.).
I have tried to figure out how to implement this but it is frankly a bit over my head.
Has anybody else tried to achieve something similar?
Edit:
I have figured out a way to achieve what I want. It's not pretty but I thought I should post it anyway, so maybe others can come up with better ideas.
In gmaps4rails.base.js.coffee I have added this method:
create_OSM : ->
OSMMapTypeOptions = new google.maps.ImageMapType(
getTileUrl: (coord, zoom) ->
"http://tile.openstreetmap.org/" + zoom + "/" + coord.x + "/" + coord.y + ".png"
tileSize: new google.maps.Size(256, 256)
name: "OSM"
maxZoom: 18
)
#serviceObject.mapTypes.set("OSM", OSMMapTypeOptions)
CycleMapTypeOptions = new google.maps.ImageMapType(
getTileUrl: (coord, zoom) ->
"http://tile.opencyclemap.org/cycle/" + zoom + "/" + coord.x + "/" + coord.y + ".png"
tileSize: new google.maps.Size(256, 256)
name: "Cycle"
maxZoom: 18
)
#serviceObject.mapTypes.set("OCM", CycleMapTypeOptions)
#serviceObject.setMapTypeId("OSM")
In js_builder.rb I added the method call like this #js << "#{gmap_id}.create_OSM();" just after #js << "#{gmap_id}.initialize();".
Lastly, my view code looks like this:
<%= gmaps("markers" => {"data" => #json},
"map_options" => {"type" => "TERRAIN", :raw => '{mapTypeControlOptions: {mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.TERRAIN, "OSM", "OCM"], style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}}'}) %>
It works and I am pleased with the result. Needs some serious cleaning up and refactoring though. Any commments?

Related

Angular Animations - Dynamic and Responsive translations

I have a component that is usually dormant (by which I simply mean it is of little interest to the user), but in a certain state this component becomes 'activated' and I want to put it in the exact center of the screen and enlarge it to grab the user's attention.
There are several of these components in the dormant state, but only ever 1 activated. The dormant components could be anywhere on the screen, so I wanted a solution that would translate the component from wherever it was originally to the middle of the screen while activated, and then return it back to its original dormant position when done.
Attempting to do this:
template:
<div #myElement [#isActivated]="activated">
Hello Stack Overflow
<button (click)="activated = activated === 'activated' ? 'dormant' : 'activated">
Toggle
</button>
</div>
typescript:
#Component({
// ...
animations: [
trigger('isActivated', [
state('dormant', style($transitionToActivated)),
state('activated', style({
transform: 'translateX(0%) translateY(0%) scale(1)'
})),
transition('dormant => activated', animate('1000ms ease')),
transition('activated => dormant', animate('1000ms ease'))
])
]
})
export class MyComponent implements OnInit {
#ViewChild('myElement') myElement: ElementRef;
activated = 'dormant';
transitionToActivated: any;
ngOnInit() {
let rect = this.myElement.nativeElement.getBoundingClinetRect();
this.transitionToActivated = {
transform: ''translateX(' + ((window.screen.width / 2) - (rect.right + rect.left) / 2) + ') translateY(' +
((window.screen.height / 2) - (rect.top + rect.bottom) / 2) + ') scale(1.5)'
}
}
}
My syntax here is off: the $transitionToActivated inside of the Component decorator is invalid. Is it possible to this kind of responsive animations with Angular Animations? Or will I need to look into a pure CSS solution?
[here's a plunker of what I'm trying... currently my attempt to put it in the exact center is commented out, and just some static animation instructions]
I figured out a couple things.
First, above I'm using window.screen for width and height of the 'screen.' This is actually giving me the resolution of the monitor (resizing the window doesn't affect it). I wanted document.documentElement to get the size of the viewport.
Second, I solved the issue of dynamic animations by using the AnimationPlayer to define the animations programmatically [rather than defining them in the Component decorator as I was trying to above].
I'm still curious as to whether the animations can be dynamically changed via the animation property inside the component decorator... I expect there must be a way, but I've been rather frustrated by the hand-wavy-ness of the Angular animations API and still can't figure it out.
Also, my solution acts funky when the viewport size is changed while in the 'activated state' (doesn't respond to resizing [as would be expected] and jumps at the start of its 'return' animation to the new middle of the viewport [again as expected].
Here's code and plunker to my solution:
export class App implements OnInit {
#ViewChild('myElement') myElement: ElementRef;
activated: BehaviorSubject<string> = new BehaviorSubject<string>('dormant');
transitionToActivated: any;
player: AnimationPlayer;
factory: any;
constructor(private builder: AnimationBuilder) {}
ngOnInit() {
console.log('viewport width: ' + document.documentElement.clientWidth);
console.log('viewport height: ' + document.documentElement.clientHeight);
let rect = this.myElement.nativeElement.getBoundingClientRect();
console.log('rect right: ' + rect.right);
console.log('rect left: ' + rect.left);
this.transitionToActivated = 'translateX(' + ((document.documentElement.clientWidth / 2) -
(rect.right + rect.left) / 2) + 'px) translateY(' +
((document.documentElement.clientHeight / 2) - (rect.top + rect.bottom) / 2) +
'px) scale(1)';
this.activated.subscribe(newValue => {
this.transitionToActivated = 'translateX(' + ((document.documentElement.clientWidth / 2) -
(rect.right + rect.left) / 2) + 'px) translateY(' +
((document.documentElement.clientHeight / 2) - (rect.top + rect.bottom) / 2) +
'px) scale(1)';
console.log(this.transitionToActivated);
if(newValue === 'activated'){
this.factory = this.builder.build([
style({ transform: 'translateX(0) translateY(0) scale(1)' }),
animate(
'1000ms',
style({ transform: this.transitionToActivated })
)
]);
this.player = this.factory.create(this.myElement.nativeElement, {});
this.player.play()
} else if(newValue === 'dormant'){
this.factory = this.builder.build([
style({ transform: this.transitionToActivated })
animate(
'1000ms',
style({ transform: 'translateX(0) translateY(0) scale(1)' }),
)
]);
this.player = this.factory.create(this.myElement.nativeElement, {});
this.player.play()
}
})
}
}

Rails 5 jquery file upload image orientation rotated 90 degrees for portraits

I'm having trouble with the image orientation after uploading an image to my s3 account. Portrait images are rotated 90 degrees when images are displayed. Here is the coffee script I am using from the Heroku - Direct to S3 Image Uploads in Rails tutorial.
# Use this instead of jQuery -> with Turbo links. Turbo links will trigger the ready page:load.
document.addEventListener 'turbolinks:load', ->
$('.directUpload').find('input:file').each (i, elem) ->
fileInput = $(elem)
form = $(fileInput.parents('form:first'))
submitButton = form.find('input[type="submit"]')
progressBar = $('<div class=\'bar\'></div>')
barContainer = $('<div class=\'progress\'></div>').append(progressBar)
fileInput.after barContainer
fileInput.fileupload
fileInput: fileInput
url: form.data('url')
type: 'POST'
autoUpload: true
formData: form.data('form-data')
paramName: 'file'
dataType: 'XML'
replaceFileInput: false
progressall: (e, data) ->
progress = parseInt(data.loaded / data.total * 100, 10)
progressBar.css 'width', progress + '%'
return
start: (e) ->
submitButton.prop 'disabled', true
progressBar.css('background', 'green').css('display', 'block').css('width', '0%').text 'Loading...'
return
done: (e, data) ->
submitButton.prop 'disabled', false
progressBar.text 'Uploading done'
# extract key and generate URL from response
key = $(data.jqXHR.responseXML).find('Key').text()
url = '//' + form.data('host') + '/' + key
# create hidden field
input = $('<input />',
type: 'hidden'
name: fileInput.attr('name')
value: url)
form.append input
return
fail: (e, data) ->
submitButton.prop 'disabled', false
progressBar.css('background', 'red').text 'Failed'
return
return
return
I'm using an image_tag to display the image from my S3 account.
= image_tag current_company.logo.image_url
I'm not sure what I need to do to fix the orientation. I did find this in the blueimp/jQuery-File-Upload/wiki/Options#imageorientation, but have no clue if this is what I am looking for or how to use it if it is. Any help would be appreciated.
This is my first time posting on here so please be gentle.

SharePoint 2010 Wiki Template Script Issue

I'm looking for a way to give my SharePoint users a way to create new wiki pages from an existing template. In the process of researching I found a great walkthrough that seems to fit the need (http://www.mssharepointtips.com/tip.asp?id=1072&page=2), but I'm having trouble getting it to work. The problem seems to lie in the assignment of a path to PATHTOWIKI-- if I use "/Weekly Update Wiki", the script returns an error of "There is no Web named '/Weekly Update Wiki'." If I use "Weekly Update Wiki" without the forward slash, I instead get an error of "There is no Web named '/sites/[parentSite]/[childSite]/Weekly Update Wiki/Weekly Update Wiki'."
Any ideas about what I'm not understanding here?
function myCreateProject() {
// Configure these for your environment
// include no slashes in paths
var PATHTOWIKI = "Weekly Update Wiki";
var PATHTOPAGES = "Pages";
// file name only for template page, no extension
var TEMPLATEFILENAME = "Template";
var myPathToWiki = encodeURIComponent(PATHTOWIKI);
var myPathToPages = PATHTOPAGES + "%2f";
var myTemplateFileName = encodeURIComponent(TEMPLATEFILENAME) + "%2easpx";
var EnteredProject = document.getElementById("NewProjName");
var myNewName = EnteredProject.value;
if(myNewName == "") {
alert('Please enter a name for the new project page');
} else {
myNewName = encodeURIComponent(myNewName) + "%2easpx"
$.ajax({
url: PATHTOWIKI + "/_vti_bin/_vti_aut/author.dll",
data: ( "method=move+document%3a14%2e0%2e0%2e4730&service%5fname="
+ myPathToWiki +
"&oldUrl=" + myPathToPages + myTemplateFileName +
"&newUrl=" + myPathToPages + myNewName +
"&url%5flist=%5b%5d&rename%5foption=nochangeall&put%5foption=edit&docopy=true"
),
success: function(data) {
var rpcmsg1 = getMessage(data, "message=", "<p>");
$("#myInfo").append("<br />" + rpcmsg1);
if(rpcmsg1.indexOf("successfully") < 0) {
// get error info
var rpcmsg2 = getMessage(data, "msg=", "<li>");
$("#myInfo").append("<br />" + rpcmsg2 + "<br />");
} else {
$("#myInfo").append("<br />Go to new page<br />");
}
},
type: "POST",
beforeSend: function(XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("X-Vermeer-Content-Type",
"application/x-www-form-urlencoded");
}
});
}
}
Update: I figured out what needed to happen in my case. Since I couldn't get a grasp on the relative approach, I just went with the absolute path for PATHTOWIKI and slightly modified the append in the ajax call.
PATHTOWIKI:
var PATHTOWIKI = "https://[domain]/sites/[parentSite]/[childSite]";
append:
$("#myInfo").append("<br />Go to new page<br />");
The change in the latter line of code is subtle; since I used an absolute path in PATHTOWIKI, I just removed the leading forward slash in the anchor tag, so that <a href=\"/" became <a href=\"". This renders the script slightly less portable, but since it's a one-off effort I'll stick with this unless anything comes along to expand the scope.

is there any more standard way to resume function from jQuery ajax call?

I am trying to write a big project which involves of a lot of code. That's why I want to separate functionalities from different files.
the first file, dataJS, I make an AJAX call to get data from a JSON file.
the second file, showJS I want to display the data obtained from the dataJS file.
When it comes to implementation, I realise that AJAX call takes longer time and even though I include dataJS and showJS in order, showJS will still get a null data
therefore I made a function called continueFromDataJS() in showJS file
and call continueFromDataJS() at the end of the AJAX success function.
I think it's a rather makedo solution. Is there any standard way to do it?
In addition, all intellisense in my Visual Studio is gone. Despite separate files, is there any way to make visual studio get intellisense from the dataJS?
Thank you
sorry, I don't know how to add a follow up question
this is the code
for simplicity I rename some of the files and only take some part out of it. Hope that helps
code in html
code in dataJS.js
var planets = [];
var jsonData = null;
$(function () {
$.getJSON("Scripts/planetData.js", function (data) {
//planets[0] = new planet("uranus", "career", 45, 700, 400, 0.1, 5, 3);
jsonData = data;
for (var i = 0; i < data.planets.length; i++) {
var curPlanet = data.planets[i];
planets[i] = new planet(curPlanet.graphic, i, curPlanet.field, curPlanet.planetInitialAngle, curPlanet.distanceFromStar, curPlanet.planetRadius, curPlanet.planetRevolvingSpeed, curPlanet.planetRotationSpeed, curPlanet.contents.length);
$("#result").append("<p>" + curPlanet.graphic + " " + curPlanet.field + " " + curPlanet.planetInitialAngle + " " + curPlanet.distanceFromStar + " " + curPlanet.planetRadius + " " + curPlanet.planetRevolvingSpeed + " " + curPlanet.planetRotationSpeed + " " + curPlanet.contents.length + "</p>");
}
callDisplayScript(); //**continue from showJS.js file is that the way to do this?**
});
});
// more functions below in dataJS.js
showJS.js
function callDisplayScript() { **// this is the ugly part. What's the proper way to do it?**
$("#display #close").click(function () {
$("#display").fadeOut('slow');
});
$article = $("#display article");
$article.empty();
var data = jsonData.planets[pID].contents; // **this line won't get jsonData if it's out this curly brace.**
for (var i = 0; i < data.length; i++) {
$article.append(data[i].title);
$article.append(data[i].content);
}
$("#display").fadeIn('slow');
};
don't forget to answer my intellisense question. I want in datajs.js automatically hint planets and jsonData declared in datajs.js
is it possible?

MediaElement.js dynamic content not working in IE9

I'm trying to use MediaElement.js on a site and everything works great in every browser but IE, most specifically IE9 (I'm not too concerned with supporting below IE9 at the moment). I'm populating the ME dynamically which I've read can cause problems in IE specifically, but I'm just not sure if there is a workaround. The reason I'm doing it this way is because this is a portfolio site where all project data gets loaded through a getJSON call and once loaded all projects get populated with their appropriate data and created on the fly. There are several video projects. I've dumbed the code down to an example outside of my project which essentially goes through this same behavior. If I just write the HTML out and control in JS it works but when I create the HTML through JS and then try to play I get the error log (in the creation of ME player in the code). Here is the code:
$(function() {
var details = {
width: 640,
height: 480,
src: 'work/television/1'
},
$body = $('body'),
$vid = $('<video width="' + details.width + '" height="' + details.height + '" preload="none" id="vidPlayer1"></video>'),
$mp4 = $('<source src="' + details.src + '.mp4" type="video/mp4" title="mp4">'),
$webm = $('<source src="' + details.src + '.webm" type="video/webm" title="webm">'),
$ogg = $('<source src="' + details.src + '.ogv" type="video/ogg" title="ogg">'),
$flash = $('<object width="' + details.width + '" height="' + details.height + '" type="application/x-shockwave-flash" data="swf/flashmediaelement.swf"><param name="movie" value="swf/flashmediaelement.swf"><param name="flashvars" value="controls=true&file=' + details.src + '.mp4"></object>'),
$error = $('<p>The available video formats are not supported by your browser. :(</p>'),
$controls = $('<div class="videoControls playBtn"></div>');
$body.append($controls);
$vid.append($mp4);
$vid.append($webm);
$vid.append($ogg);
$vid.append($flash);
$vid.insertAfter($controls);
var vidPlayer = new MediaElementPlayer('#vidPlayer1', {
features: [],
// mode: 'shim',
pluginPath: 'swf/',
success: function(mediaElement) {
console.log('success', mediaElement);
},
error: function() {
console.log('Error loading player. Please try again.');
}
});
$body.on('click', function(evt) {
vidPlayer.play();
});
});
Any help would be tremendously appreciated.
problem solved. for anyone interested, had to combine my appends into one call so $vid became:
$vid = $('<video width="' + details.width + '" height="' + details.height + '" preload="none" id="vidPlayer-' + row + '-' + slide + '"><source src="' + details.src + '.mp4" type="video/mp4" title="mp4"><source src="' + details.src + '.webm" type="video/webm" title="webm"><source src="' + details.src + '.ogv" type="video/ogg" title="ogg"><p>The available video formats are not supported by your browser. :(</p></video>')
just had to put it all in one statement and IE9 recognized it properly. The issue was by appending as I was doing the source variables never got appended and thus IE didn't know what the source of my video was.
Hope this helps someone in the future.