I have a PCL project and recently updated the Xamarin forms to version 2.3.4.270 but it seems that after updating to this version the webview.navigated() event does not fire.
var browser = new BaseUrlWebView ();
var htmlSource = new HtmlWebViewSource ();
htmlSource.Html = #"<html>
<head>
<link rel=""stylesheet"" href=""default.css"">
</head>
<body>
<h1>Xamarin.Forms</h1>
<p>The CSS and image are loaded from local files!</p>
<img src='XamarinLogo.png'/>
<p>next page</p>
</body>
</html>";
htmlSource.BaseUrl = DependencyService.Get<IBaseUrl> ().Get ();
browser.Navigated += (sender, e) => {
this.DisplayAlert("Navigated", "Navigated the page", "Cancel");
};
browser.Source = htmlSource;
Content = browser;
var browser = new BaseUrlWebView ();
var htmlSource = new HtmlWebViewSource ();
htmlSource.Html = #"Some HTML";
htmlSource.BaseUrl = DependencyService.Get<IBaseUrl> ().Get ();
browser.Source = htmlSource;
browser.Navigated += WebViewOnNavigated;
Content = browser;
private async void WebViewOnNavigated(object sender, WebNavigatedEventArgs e){
await DisplayAlert("Navigated", "Navigated the page", "Cancel");
}
Related
I am using ImageCropper and MediaPlugin to Upload images. However I have problem getting the image after cropping the image.
string imagefile;
protected void OnClickedRectangle(object sender, EventArgs e)
{
new ImageCropper()
{
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
});
}
}.Show(this);
}
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var content = new MultipartFormDataContent();
content.Add(new StreamContent(imageFile), "files", imagefile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxx/api/Upload", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
However how can I get the Image to upload. note that view_imageavatar still shows the image after cropping. Tks!
Update...
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var fileStream = File.OpenRead(imageFile);
var fileContent = new StreamContent(fileStream);
var content = new MultipartFormDataContent();
content.Add(fileContent, "files", imageFile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
It still doesn't work?
Update 2
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var upfilebytes = File.ReadAllBytes(imageFile);
var ms = new MemoryStream(upfilebytes);
var content = new MultipartFormDataContent();
content.Add(new StreamContent(ms), "files", imageFile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
-> It still can't upload photos through the API?
However I try not to use ImageCropper. I upload directly.
async void edit_avatar_Tapped(object sender, EventArgs e)
{
var file = await MediaPicker.PickPhotoAsync();
var content = new MultipartFormDataContent();
content.Add(new StreamContent(await file.OpenReadAsync()), "files", file.FileName);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
string a = responses.StatusCode.ToString();
}
--> Then it works fine, the image is uploaded through the API
Does the image load from content.Add(new StreamContent(ms), "files", imageFile); it doesn't work with API? Looking for solutions from everyone.
Have you actually checked what StreamContent takes as arguments?
It takes a Stream not a path to a file.
You need to open the file first like so:
using var fileStream = File.Open(imageFile);
using var fileContent = new StreamContent(fileStream);
Have you tried something like that?
In a blazor wasm, I want to create a pdf and make it downloadable. I tested pdfflow, but was only able to make it run in a console application. There are several commercial solutions (devexpress, syncfusion), but they are really expensive.
Next, I stepped over the blog post Generate PDF files using an html template and Playwright, that seemed much promising to me. Unfortunately, it does not contain a complete example and I cannot make it run. Here is, what I tried:
I added template.html to wwwroot folder.
template.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="invoice.css">
</head>
<body style="padding: 3rem">
<h1>Invoice</h1>
Awesome company<br />
</body>
</html>
I added a button, that invokes CreatePdf(). I copied the code from the link above and modified it according to my needs (and because e. g. there is no method LoadOrder(orderId) provided).
Index.razor
#page "/"
#using Scriban
#using System.IO
#using Microsoft.Playwright
#inject HttpClient Http
<button class="btn btn-primary" #onclick="CreatePdf">pdf</button>
#code{
private async Task CreatePdf()
{
//var templateContent = File.ReadAllText("template.html");
var templateContent = await Http.GetStringAsync("template.html");
var template = Template.Parse(templateContent);
//var templateData = new { Invoice = LoadOrder(orderId) };
//var pageContent = template.Render(templateData);
var pageContent = "testString";
//var dataUrl = "data:text/html;base64," + Convert.ToBase64String(Encoding.UTF8.GetBytes(pageContent));
var dataUrl = "data:text/html;base64," + pageContent;
I added the following two lines, because "browser" was not declared (Source from playwright).
// Here, the app crashes.
using var playwright = await Playwright.CreateAsync();
var browser = await playwright.Webkit.LaunchAsync();
await using var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();
await page.GotoAsync(dataUrl, new PageGotoOptions { WaitUntil = WaitUntilState.NetworkIdle });
var output = await page.PdfAsync(new PagePdfOptions
{
Format = "A4",
Landscape = false,
});
await File.WriteAllBytesAsync("output.pdf", output);
} }
How can i make above code run?
You cannot use Playwright from a browser (js / wasm). So, you have to use another solution. For instance, you can use jsPDF. This library is not perfect when converting html to pdf, but maybe it will be ok for your usage.
Add a few script references in index.html to use jsPDF (you can also install them using npm if you prefer)
<script src="_framework/blazor.webassembly.js"></script>
<!-- jsPDF references -->
<script src="https://unpkg.com/jspdf#latest/dist/jspdf.umd.min.js"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dompurify#2.3.3/dist/purify.min.js"></script>
Create a file wwwroot/HtmlToPdf.js with the following content:
export function generateAndDownloadPdf(htmlOrElement, filename) {
const doc = new jspdf.jsPDF({
orientation: 'p',
unit: 'pt',
format: 'a4'
});
return new Promise((resolve, reject) => {
doc.html(htmlOrElement, {
callback: doc => {
doc.save(filename);
resolve();
}
});
});
}
export function generatePdf(htmlOrElement) {
const doc = new jspdf.jsPDF();
return new Promise((resolve, reject) => {
doc.html(htmlOrElement, {
callback: doc => {
const output = doc.output("arraybuffer");
resolve(new Uint8Array(output));
}
});
});
}
Then, you can use the script from a Razor component:
#inject IJSRuntime JSRuntime
<button type="button" #onclick="DownloadPdf">Generate</button>
#code {
async Task DownloadPdf()
{
await using var module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./HtmlToPdf.js");
// Generate and download the PDF
await module.InvokeVoidAsync("generateAndDownloadPdf", "<h1>sample</h1>", "sample.pdf");
// Generate the PDF and get its content as byte[] (need .NET 6 to support Uint8Array)
var bytes = await module.InvokeAsync<byte[]>("generatePdf", "<h1>sample</h1>");
}
}
I have a simple login webpage which loads up in a WebView in a ContentPage in Xamarin. I have added the JavaScript renderer as shown here (https://www.xamarinhelp.com/xamarin-forms-webview-executing-javascript/) and it works fine. I am able to retrieve the values of the textbox in this way:
var email = await EvaluateJavascript("document.getElementById('Email').value;");
But is there a way in which I can set the default value of the textbox when the WebView loads. Making changes to the html of the WebView is not an option here.
I tried doing this but it doesn't work :
await EvaluateJavascript("document.getElementById('Email').value = 'defaultemail#email.com';");
is there a way in which I can set the default value of the textbox when the WebView loads. Making changes to the html of the WebView is not an option here.
This answer is No, It cannot be achieved. If we want to set the value for textBox from html. This webview This webview must be finished loading.
So when you used await EvaluateJavascript("document.getElementById('Email').value = 'defaultemail#email.com';"); it not worked.
If we use await EvaluateJavascript("document.getElementById('Email').value = 'defaultemail#email.com';"); when webview is finished loading.it will worked.
So we can create webview's custom renderer. Override the OnPageFinished method in MyWebviewClient, if page finshed loading, we can send an messageCenter.
[assembly: ExportRenderer(typeof(WebView), typeof(MyWebview))]
namespace XFormsWebview.Droid
{
class MyWebview : WebViewRenderer
{
public MyWebview(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
Control.Settings.JavaScriptEnabled = true;
Control.SetWebViewClient(new MyWebviewClient());
}
}
internal class MyWebviewClient : Android.Webkit.WebViewClient
{
public override void OnPageFinished(Android.Webkit.WebView view, string url)
{
base.OnPageFinished(view, url);
MessagingCenter.Send<App, string>(App.Current as App, "OpenPage", "finish");
}
}
}
In the PCL, if we get the message. we can set it value by mywebview.EvaluateJavaScriptAsync("document.getElementById('txt').value= 'my url that I want to copy';");.
namespace XFormsWebview
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
mywebview.Source = LoadHTMLFileFromResource();
MessagingCenter.Subscribe<App, string>(App.Current, "OpenPage", (snd, arg) =>
{
Device.BeginInvokeOnMainThread(() => {
mywebview.EvaluateJavaScriptAsync("document.getElementById('Email').value= 'defaultemail#email.com';");
});
});
}
HtmlWebViewSource LoadHTMLFileFromResource()
{
var source = new HtmlWebViewSource();
// Load the HTML file embedded as a resource in the .NET Standard library
var assembly = typeof(MainPage).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream("XFormsWebview.indexd.html");
using (var reader = new StreamReader(stream))
{
source.Html = reader.ReadToEnd();
}
return source;
}
}
}
Here is my html page.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>www.test.net</title>
</head>
<body>
<script language="javascript">
function c1(myvalue)
{
var t=document.getElementById("Email");
t.value="ttt";
}
</script>
<input type="text" id="Email" value="init content" size="30"/>
<input type="button" value="change" name="btn" onclick="c1();" />
</body>
</html>
Here is running screenshot.
I use the https://github.com/erikvold/toolbarbutton-jplib/ package to add a toolbar button from an addon-sdk addon to the firefox navigation bar. Is it possible to add a drop down menu to this button (as I understand there are no easy ways)?
This is how I do it; hope it works for you.
var winUtils = require("window-utils");
var delegate = {
onTrack: function(window) {
if(window.location != "chrome://browser/content/browser.xul") {
// console.log("=> win location false");
return;
}
console.log("window tracked");
var document = window.document;
var navBar = document.getElementById('nav-bar');
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', 'button');
btn.setAttribute('type', 'menu-button');
btn.setAttribute('class', 'toolbarbutton-1');
btn.setAttribute('image', 'http://www.facebook.com/favicon.ico');
btn.addEventListener('command', function() {
console.log("this=" + this.id);
// your callback code here
}
, false);
var menupopup = document.createElement('menupopup');
menupopup.setAttribute('id', 'menupopup');
menupopup.addEventListener('command', function(event) {
// TODO your callback
}
, false);
//menu items
var menuitem1 = document.createElement('menuitem');
menuitem1.setAttribute('id', 'menuitem1');
menuitem1.setAttribute('label', 'Menu item1');
menuitem1.setAttribute('class', 'menuitem-iconic');
menuitem1.addEventListener('command', function(event) {
// CODE
}
, false);
}
winUtils.WindowTracker(delegate);
This code requires a few more lines to actually work:
var delegate = {
onTrack: function(window) {
if(window.location != "chrome://browser/content/browser.xul") {
// console.log("=> win location false");
return;
}
var document = window.document;
var navBar = document.getElementById('nav-bar');
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', 'button');
btn.setAttribute('type', 'menu-button');
btn.setAttribute('class', 'toolbarbutton-1');
btn.setAttribute('image', 'http://www.facebook.com/favicon.ico');
btn.addEventListener('command', function() {
console.log("this=" + this.id);
// your callback code here
}
, false);
var menupopup = document.createElement('menupopup');
menupopup.setAttribute('id', 'menupopup');
menupopup.addEventListener('command', function(event) {
// TODO your callback
}
, false);
//menu items
var menuitem1 = document.createElement('menuitem');
menuitem1.setAttribute('id', 'menuitem1');
menuitem1.setAttribute('label', 'Menu item1');
menuitem1.setAttribute('class', 'menuitem-iconic');
menuitem1.addEventListener('command', function(event) {
// CODE
}
, false);
menupopup.appendChild(menuitem1);
btn.appendChild(menupopup);
navBar.appendChild(btn);
console.log("window tracked");
}
};
//let utils = require('api-utils/window-utils');
let utils = require('sdk/deprecated/window-utils'); // for new style sdk
utils.WindowTracker(delegate);
I have problem with Firefox6 (don't know if it also concerns earlier versions).
I want to embed Google Map on page, and when page has scrollbars (is longer than viewport) mouse wheel not only zooms map but also scrolls page. I tried to catch mousewheel event and stop propagation but this event isn catchable when cursor os over map. When cursor is over map controls (zoom control, google logo, etc) i can catch event and stop propagation.
What is more strange it not happens always. Sometimes page srolls and after few scrolls it stops and mousewheel only zooms map (as expected). Sometimes page doesn't scroll and sometimes it scrolls with zoom all the time. Can't find pattern.
Source code is simple:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>test</title>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
window.onload = function(){
var latlng = new google.maps.LatLng(52.25, 21.01);
mapOptions = {
zoom: 12,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: false,
zoomControl:true,
mapTypeControl:false
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
}
</script>
</head>
<body>
<p style="height:500px;">-lot of text-</p>
<div id="map_canvas" style="width:500px; height:500px;"></div>
<p style="height:500px;">-lot of text-</p>
</body>
</html>
Your problem is also described on code.google.com, this problem is only in Firefox, but it isn't a Firefox bug:
http://code.google.com/p/gmaps-api-issues/issues/detail?id=3652
http://code.google.com/p/gmaps-api-issues/issues/detail?id=1605
Have also found out a workaround, that is not re-scrolling or re-zooming and works fine:
A new ScrollInterceptOverlay derived from google.maps.OverlayView, prepending a div on MapPanes.overlayMouseTarget:
Version with jQuery
// Ensure to have google.maps loaded:
// var gmap = new google.maps.Map($googlemap[0], mapOptions);
// Define a ScrollInterceptOverlay function
var ScrollInterceptOverlay = function (gmap) {
if (!(this instanceof ScrollInterceptOverlay)) return;
var $div;
var $mapDiv;
var initialize = function () {
$div = $('<div />').css({
position: 'absolute', top: 0, left: 0,
display: 'inline-block'
});
var div = $div[0];
if (div && div.addEventListener) {
// Internet Explorer, Opera, Google Chrome and Safari
div.addEventListener("mousewheel", mouseScrollStop);
// Firefox
div.addEventListener("DOMMouseScroll", mouseScrollStop);
div.addEventListener("MozMousePixelScroll", mouseScrollStop);
}
else if (div && div.attachEvent) { // IE before version 9
div.attachEvent("onmousewheel", mouseScrollStop);
}
this.setMap(gmap);
};
var mouseScrollStop = function (e) {
if (e && e.preventDefault) e.preventDefault();
};
this.onAdd = function () {
$div.prependTo(this.getPanes().overlayMouseTarget);
};
this.onRemove = function () {
var div = $div[0];
if (div && div.addEventListener) {
// Internet Explorer, Opera, Google Chrome and Safari
div.addEventListener("mousewheel", mouseScrollStop);
// Firefox
div.addEventListener("DOMMouseScroll", mouseScrollStop);
div.addEventListener("MozMousePixelScroll", mouseScrollStop);
}
else if (div && div.attachEvent) { // IE before version 9
div.attachEvent("onmousewheel", mouseScrollStop);
}
$div.detach();
};
this.draw = function () {
if ($mapDiv && $mapDiv.length === 1) {
$div.css({
width: $mapDiv.outerWidth(),
height: $mapDiv.outerHeight()
});
}
};
var base_setMap = this.setMap;
this.setMap = function (map) {
$mapDiv = $(map.getDiv());
base_setMap.call(this, map);
};
initialize.call(this);
};
// Setup prototype as OverlayView object
ScrollInterceptOverlay.prototype = new google.maps.OverlayView();
// Now create a new ScrollInterceptOverlay OverlayView object:
var mapScrollInterceptor = new ScrollInterceptOverlay(gmap);
This workaround is using jQuery, required for calculating outerWidth and outerHeight, but also for better reading.
Version with pure javaScript
Tested live: http://fiddle.jshell.net/fhSMM/7/
// Ensure to have google.maps loaded:
// var gmap = new google.maps.Map(googlemap, mapOptions);
// Define a ScrollInterceptOverlay class function
var ScrollInterceptOverlay = function () {
if (!(this instanceof ScrollInterceptOverlay)) return;
var div;
// private instance function
var mouseScrollStop = function (e) {
if (e && e.preventDefault) e.preventDefault();
};
// public instance function
this.onAdd = function () {
div = document.createElement('div');
div.style.display = 'inline-block';
div.style.position = 'absolute';
div.style.top = div.style.left = 0;
if (div.addEventListener) {
// Internet Explorer, Opera, Google Chrome and Safari
div.addEventListener("mousewheel", mouseScrollStop);
// Firefox
div.addEventListener("DOMMouseScroll", mouseScrollStop);
div.addEventListener("MozMousePixelScroll", mouseScrollStop);
}
else if (div.attachEvent) { // IE before version 9
div.attachEvent("onmousewheel", mouseScrollStop);
}
var pane = this.getPanes().overlayMouseTarget;
var firstChild = pane.firstChild;
if (!firstChild) {
pane.appendChild(div);
}
else {
pane.insertBefore(div, firstChild);
}
};
// public instance function
this.onRemove = function () {
if (div) {
if (div.removeEventListener) {
// Internet Explorer, Opera, Google Chrome and Safari
div.removeEventListener("mousewheel", mouseScrollStop);
// Firefox
div.removeEventListener("DOMMouseScroll", mouseScrollStop);
div.removeEventListener("MozMousePixelScroll", mouseScrollStop);
}
else if (div.detachEvent) { // IE before version 9
div.detachEvent("onmousewheel", mouseScrollStop);
}
var parent = div.parentNode;
parent.removeChild(div);
}
// do not delete div var'iable
div = undefined;
};
// public instance function
this.draw = function () {
var map = this.getMap();
if (map) {
var mapDiv = map.getDiv();
if (mapDiv) {
var rect = mapDiv.getBoundingClientRect();
div.style.width = rect.width + 'px';
div.style.height = rect.height + 'px';
}
}
};
};
// Setup prototype as OverlayView object
ScrollInterceptOverlay.prototype = new google.maps.OverlayView();
// Now create a new ScrollInterceptOverlay OverlayView object:
var mapScrollInterceptor = new ScrollInterceptOverlay();
mapScrollInterceptor.setMap(gmap);
Please visit also http://metadea.de/V/ about what (real) javaScript class functions are, and why I like jQuery :)
Works now for me.
Also in Firefox, the map is zooming on mousescroll, but no more scrolling the document.
Edit: Updated support for MozMousePixelScroll, refined jS
For now it looks like firefox bug. Will close question when bug will be fixed.
I had the same issue.
You could try to start Firefox with a brand new profile (e.g. by starting the Profile Manager - executing 'firefox -P' on windows systems - and choosing 'Create...') and see if the problem persists.
I had several old but seemingly empty user profiles lying around in the VMs I used to verify if this was a bug in FF 6 and obviously installing only the new binaries didn't help. On the other hand, creating a blank profile did, so I can only think of this being a migration glitch. If major versions of FF are going to be released on a bi-monthly basis, though, a lot of people are going to suffer from similar issues.
Why not take UI control of zooming? This works well for me.
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
</head>
<body>
<div class="canvas" style="width:600px;height:400px;"></div>
<script>
// Load event
$(function() {
var myOptions = {
zoom: 8,
center: new google.maps.LatLng(-34.397, 150.644),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map($('.canvas')[0], myOptions);
var overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
// Only a Mozilla bug
if($.browser.mozilla) {
// Wait for the map DOM to be ready
google.maps.event.addListenerOnce(map, 'idle', function() {
$('.canvas > div > div:first-child > div').bind('DOMMouseScroll', function(e) {
// setTimeout needed otherwise the return false has no effect
setTimeout(function() {
// Calculate new center
var offset = $('.canvas').offset();
var pos = overlay.getProjection().fromContainerPixelToLatLng(new google.maps.Point(e.pageX-offset.left, e.pageY-offset.top));
// Calculate new zoom level
var zoom = map.getZoom();
if(e.detail < 0) zoom++;
else if(e.detail > 0) zoom--;
map.setCenter(pos);
map.setZoom(zoom);
}, 1);
// Stop propagation (prevent default)
return false;
});
});
}
});
</script>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</body>
</html>