WebView.InvokeScript always returns empty string - webview

I've got a problem with WebView control. I'm developing Windows 8 Metro Style app and I'm trying to invoke script in content of WebView, but it's always returns empty string.
I've tried to make it "WebView.InvokeScript("eval", new string[] { "document.getElementById('contentDiv').offsetHeight" }) as well but it works the same - empty string. I really have no guesses what wrong is here.
public void Sethtml(string html) {
var toSet = string.Format(Style, html);
wv.LoadCompleted += wv_LoadCompleted;
wv.NavigateToString(toSet);
}
void wv_LoadCompleted(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
WebView wv = sender as WebView;
string height = wv.InvokeScript("heightFun", new string[0]);
}
public static readonly string Style = #"<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
body {{
font-family: Segoe UI;
}}
</style>
<script type='text/javascript'>
var heightFun = function() {{
return document.getElementById('contentDiv').offsetHeight;
}}
</script>
</head>
<body>
<div id='contentDiv'>
{0}
</div>
</body>";

You must use the window.external.notify to send a value back.
See the forum post:
http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/ac390a6a-d4ad-408c-8b13-93f9694cbabe

Just solved this problem via a hint of the previous answer.
Make sure your return value is a string.

Related

Client-side, then() or other?

How i can use "Future" in client-side ?
And, how I can block the execution of my code, while no event is catch ?
import 'dart:html';
import 'dart:convert';
import 'dart:async';
Map data;
Future<String> ft_get_pseudo()
{
InputElement button;
InputElement text;
text = querySelector('[name="pseudo"]');
button = querySelector('[name="push"]');
button.onClick.listen((_) => text.value);
}
void main()
{
WebSocket wss;
String encode;
data = new Map();
wss = new WebSocket('ws://127.0.0.1:4040/ws');
ft_get_pseudo().then((name)
{
data['pseudo'] = name;
encode = JSON.encode(data);
wss.onOpen.listen((_) => wss.send(encode));
wss.onMessage.listen((msg) => print("Msg received : ${msg.data}"));
});
}
I saw Promise function in ecmascript 6, there is a way to use it, or the idea ?
HTML :
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<script type="application/dart" src="client.dart"></script>
<link rel="stylesheet" href="style.css" type="text/css">
<title>Client</title>
</head>
<body>
<div id="console">
</div>
<input type="text" name="pseudo" size="20" placeholder="pseudo">
<input type="button" name="push" value="Send">
</body>
</html>
For such a simple use case you can do it this way
Future<String> ft_get_pseudo()
{
return new Future(() {
InputElement button;
InputElement text;
text = querySelector('[name="pseudo"]');
button = querySelector('[name="push"]');
button.onClick.listen((_) => _completer.complete(text.value));
}
}
If I understand you correctly, you want to get text.value from the ft_get_pseudo() function when you push on the button, right? If so, you need to create a new Completer and return its Future at the end of the ft_get_pseudo(). Then, in the button's onClick event, you just complete the future with the value of text.value.
Code might be something like this:
Future<String> ft_get_pseudo()
{
Completer _completer = new Completer();
InputElement button;
InputElement text;
text = querySelector('[name="pseudo"]');
button = querySelector('[name="push"]');
button.onClick.listen((_) => _completer.complete(text.value));
return _completer.future;
}
I think you want to do something like this, but I don't yet fully understand what you try to accomplish.
Can you please just add a comment what you need differently?
Map data;
void main() {
//(querySelector('[name="push"]') as ButtonInputElement).onClick.listen(btnClickHandler);
(querySelector('[name="push"]') as ButtonInputElement).onClick.first.then(btnClickHandler);
// this would work too, because every element has the click event.
// querySelector('[name="push"]').onClick.listen(btnClickHandler);
}
void btnClickHandler(MouseEvent e) {
String name = (querySelector('[name="pseudo"]') as TextInputElement).value;
data = {'pseudo': name};
String encode = JSON.encode(data);
WebSocket wss = new WebSocket('ws://127.0.0.1:4040/ws');
wss.onOpen.listen((_) => wss.send(encode));
wss.onMessage.listen((msg) => print("Msg received : ${msg.data}"));
}

Alert does not appear on page load in .cshtml page

I have a simple .cshtml page and My problem is when I run this page alert is not shown. Here is the .cshtml page code:
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>ChartDataJSON</title>
<script type="text/javascript">
alert('hello');
</script>
</head>
<body>
<div>
<div id="chart1" ></div>
</div>
</body>
</html>
Also I have a controller class through which this view is generated. The lines written in that class are:
public class jqPlotController : Controller
{
//
// GET: /jqPlot/
public ActionResult Index()
{
return View();
}
public ActionResult ChartDataJSON()
{
var chartData = new List<jqplotModel>();
var point1 = new jqplotModel { Date = DateTime.Now.Date.ToString("yyyy-MM-dd h:mmtt"), Demand = Convert.ToDouble(1), Supply = Convert.ToDouble(3) };
var point2 = new jqplotModel { Date = DateTime.Now.AddDays(10).Date.ToString("yyyy-MM-dd h:mmtt"), Demand = Convert.ToDouble(2), Supply = Convert.ToDouble(4) };
var point3 = new jqplotModel { Date = DateTime.Now.AddDays(31).Date.ToString("yyyy-MM-dd h:mmtt"), Demand = Convert.ToDouble(6), Supply = Convert.ToDouble(6) };
var point4 = new jqplotModel { Date = DateTime.Now.AddDays(106).Date.ToString("yyyy-MM-dd h:mmtt"), Demand = Convert.ToDouble(4), Supply = Convert.ToDouble(2) };
chartData.Add(point1);
chartData.Add(point2);
chartData.Add(point3);
chartData.Add(point4);
return Json(chartData, JsonRequestBehavior.AllowGet);
}
}
Is this due to the “return” keyword in the controller class which stops alert pop up from appearing on the web page.
Has anybody faced this type of issue before. Can somebody help me in figuring out the problem?
Edit:
The view is added with respect to ChartDataJSON method of controller class.
Update: I have made following changes in view and the controller class is as mentioned above.
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>ChartDataJSON</title>
<script type="text/javascript">
$.ajax("/jqPlot/ChartDataJSON")
.done(function (data) {
// do something with the data.
alert("success");
})
</script>
</head>
<body>
<div>
<div id="chart1" ></div>
</div>
</body>
</html>
When returning JSON result you will not render out any Views (HTML markup). To return the HTML markup you must write this
return View("name of cshtml file without .cshtml");
where [name of view] is the name of the cshtml file you were referring to (without the .cshtml extension), and the model can be the data you want to use in the cshtml file.
To retrieve the data using ajax you can use this command as a example
$.ajax( "/jqPlot/ChartDataJSON" )
.done(function(data) {
// do something with the data.
alert( "success" );
})
Update:
To load the view you have to call an action that returns and renders the view. Lets say your view is named Index.cshtml and its full path is "Views/jqPlotController/Index.cshtml
Then all you have to do is call the URL of the action, http://[nameofdomain]/Index .
Then the view should be loaded and the javascript function trigger and call the action ChartDataJSON, which will return the JSON result and in this case the alert is triggered if the call to the action is successfull.

Breeze Metadata Api not getting called

I looked at the network tab on Chrome and found that my breeze api for metadata is not getting called and thus all my methods of createEntity etc are failing.
[HttpGet]
public string Metadata()
{
return _context.Metadata();
}
I have followed the todo example and have enabled CORS Support and just about everything, I can see the json metadata if i navigate to /api/breeze/metadata
I am using VS2012 Web Express and gotten all the packages thru nuget
dataservice.js
app.dataservice = (function (breeze) {
var serviceName = 'api/breeze'; // route to the same origin Web Api controller
var manager = new breeze.EntityManager(serviceName);
return {
createTodo: createTodo,
saveChanges: saveChanges
};
function createTodo(initialValues) {
return manager.createEntity('BreezeItem', initialValues);
}
function saveChanges() {
return manager.saveChanges()
.then(function () { alert('good') })
.fail(function () { alert('bad') })
}
})(breeze);
index.html
`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1"/>
<title>Breeze Todos with KO</title>
</head>
<body>
<div id="applicationHost">
<header>
<h1>Breeze Todos</h1>
<h2>with Knockout</h2>
<form data-bind="submit: addItem">
<input type="text" data-bind="value: newBreeze, valueUpdate: 'afterkeydown'" placeholder="What needs to be done?">
</form>
</header>
</div>
<!-- 3rd party libraries -->
<script src="Scripts/jquery-1.8.3.js"></script>
<script src="Scripts/knockout-2.2.1.debug.js"></script>
<script src="Scripts/q.js"></script>
<script src="Scripts/breeze.debug.js"></script>
<script src="Scripts/breeze.savequeuing.js"></script>
<!-- App libraries -->
<script>app = {};</script>
<script src="app/dataservice.js"></script>
<script src="app/viewModel.js"></script>
</body>
</html>
viewmodel.js
app.viewModel = (function ( dataservice) {
var vm = {
newBreeze: ko.observable(""),
addItem: addItem
};
return vm; // done with setup; return module variable
//#region private functions
function addItem() {
var item = dataservice.createTodo(
{
BreezeName: vm.newBreeze()
}
);
dataservice.saveChanges().fail(addFailed);
vm.newTodo("");
function addFailed() {
console.log("Failed")
}
}
function extendItem(item) {
if (item.isEditing) return; // already extended
item.isEditing = ko.observable(false);
}
})(app.dataservice);
// Bind viewModel to view in index.html
ko.applyBindings(app.viewModel);
Breeze makes the metadata call under two conditions, either implicitly as part of the first query in an application or explicity via the EntityManager.fetchMetadata method. This means that if you are not performing a query as your first action, then you will need to make a 'fetchMetadata' call instead. Remember that this is an async call that returns a 'promise', just like a query, so you will need to perform any calls to your "createEntity" methods when the promise resolves (i.e. within the 'then' call.

How to render a Section in a Partial View in MVC3?

In a MVC3 project, I have a "_Layout.vbhtml" file with this code
<!DOCTYPE html>
<html>
<head>
</head>
<body>
...
<script src="#Url.Content("~/Scripts/jquery-1.8.2.min.js")"></script>
#RenderSection("Scripts", false)
</body>
</html>
Then, I have a Partial View "ValidationScripts.vbhtml" in the Shared folder with
#Section Scripts
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.fix.js")"></script>
<script src="#Url.Content("~/Scripts/localization/messages_de.js")"></script>
End Section
If I call the Partial View from a View like this...
#ModelType MvcExample.MyModel
#Code
ViewData("Title") = "Test"
End Code
#Html.Partial("ValidationScripts")
<h2>Just a Test</h2>
...
the Section "Scripts" is not rendered on the page, and the output HTML is
<!DOCTYPE html>
<html>
<head>
</head>
<body>
...
<script src="#Url.Content("~/Scripts/jquery-1.8.2.min.js")"></script>
</body>
</html>
How can I render the Section in the Partial View ?
I had the same issue on top of duplicate scripts, so I created a couple of Extension methods:
public static class HtmlHelperExtensions
{
private const string _jSViewDataName = "RenderJavaScript";
private const string _styleViewDataName = "RenderStyle";
public static void AddJavaScript(this HtmlHelper htmlHelper,
string scriptURL)
{
List<string> scriptList = htmlHelper.ViewContext.HttpContext
.Items[HtmlHelperExtensions._jSViewDataName] as List<string>;
if (scriptList != null)
{
if (!scriptList.Contains(scriptURL))
{
scriptList.Add(scriptURL);
}
}
else
{
scriptList = new List<string>();
scriptList.Add(scriptURL);
htmlHelper.ViewContext.HttpContext
.Items.Add(HtmlHelperExtensions._jSViewDataName, scriptList);
}
}
public static MvcHtmlString RenderJavaScripts(this HtmlHelper HtmlHelper)
{
StringBuilder result = new StringBuilder();
List<string> scriptList = HtmlHelper.ViewContext.HttpContext
.Items[HtmlHelperExtensions._jSViewDataName] as List<string>;
if (scriptList != null)
{
foreach (string script in scriptList)
{
result.AppendLine(string.Format(
"<script type=\"text/javascript\" src=\"{0}\"></script>",
script));
}
}
return MvcHtmlString.Create(result.ToString());
}
public static void AddStyle(this HtmlHelper htmlHelper, string styleURL)
{
List<string> styleList = htmlHelper.ViewContext.HttpContext
.Items[HtmlHelperExtensions._styleViewDataName] as List<string>;
if (styleList != null)
{
if (!styleList.Contains(styleURL))
{
styleList.Add(styleURL);
}
}
else
{
styleList = new List<string>();
styleList.Add(styleURL);
htmlHelper.ViewContext.HttpContext
.Items.Add(HtmlHelperExtensions._styleViewDataName, styleList);
}
}
public static MvcHtmlString RenderStyles(this HtmlHelper htmlHelper)
{
StringBuilder result = new StringBuilder();
List<string> styleList = htmlHelper.ViewContext.HttpContext
.Items[HtmlHelperExtensions._styleViewDataName] as List<string>;
if (styleList != null)
{
foreach (string script in styleList)
{
result.AppendLine(string.Format(
"<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />",
script));
}
}
return MvcHtmlString.Create(result.ToString());
}
}
On any View or Partial View or Display/Edit Template you simply add what you need:
#{
Html.AddJavaScript("http://cdn.jquerytools.org/1.2.7/full/jquery.tools.min.js");
}
In your Layouts you render it where you want it:
<!DOCTYPE html>
<html lang="en">
<head>
#Html.RenderStyles()
#Html.RenderJavascripts()
The only issue you may have is the order in which the scripts are rendered if you get to complex. If that becomes an issue, simply add the scripts to the bottom of your views/templates, and simply reverse the order in the extension method before rendering them.
You can't use sections in partial views. You can go for custom helpers as mentioned here.
I think you should be using helpers for this http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx
If you can upgrade to MVC4 you could use the new bundling and minification feature: http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification . It is specifically designed to address what you are trying to achieve (including scripts).
Alternatively you could use http://combres.codeplex.com/ with MVC3
If I understand correctly you have a structure
Layout.cshtml
View - X
PartialView Y (called inside View-X)
then you need to define the
#section Script{ .... } in the View-X and NOT PartialView Y since View-X has its View.Layout set to Layout.cshtml
all this was great info, however if you look at his original code, Section is capitalized therefore not being recognized.
it should be #section blahblah not #Section

Add on-click event code to a LabelField

In my application there is a LabelField with text "www.google.com" When the user clicks, the default browser should open to www.google.com.
try this code
final LabelField label = new LabelField("http://www.google.com",LabelField.FOCUSABLE){
public boolean navigationClick (int status , int time){
BrowserSession bSession = Browser.getDefaultSession();
bSession.displayPage(label.getText());
return true;
}
};
you may use Jquery.
try this code:
<html>
<head>
<title>Opens a link</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.js"></script>
</head>
<body>
<label for="link" id="target">www.google.com</label>
<script type="text/javascript">
$('#target').click(function () {
var url = $(this).text();
window.location = "http\://"+url;
});
</script>
</body>
</html>

Resources