Tapestry properties in jQuery - javascript

I have two files: "Index.properties", "Index_es.properties" for multilenguage in Tapestry.
I want to read literals from those files in a *.js file, for example:
**Index.properties:**
menu=Main menu
menu-welcome=Welcome to my webpage
**Index_es.properties:**
menu=Menú principal
menu-welcome=Bienvenido a mi página web
**Index.tml:**
...
<script type="text/javascript" language="JavaScript"
src="${context:/javaScript/menu.js}"></script>
...
**menu.js:**
...
var currentOption=$('#activemenu').attr('name');
if (currentOption=="menu"){
$("#button1txt").text("${message:option1}");
}
...
How can I read the files since "menu.js"?
Thank you

About expansions
Expansions only work in your templates (.tml files) or in the component classes if you are using the #Component annotation, for example.
Component parameter documentation:
https://tapestry.apache.org/component-parameters.html
You cannot access files in JavaScript that are stored on the server. But you could pass them along with your script’s init script.
How to add custom scripts to your pages
Don’t do this to your template:
<script type="text/javascript" language="JavaScript" src="${context:/javaScript/menu.js}"></script>
Do this instead to your page class:
#Import(library = { "context:javaScript/menu.js" })
public class Index {
}
Read the documentation about this feature to learn more: http://tapestry.apache.org/javascript.html
Solution to your problem
With all that knowledge you’ll now rather want to pass the translations for your menu script like this:
#Import(library = { "context:javaScript/menu.js" })
public class Index {
#Inject
private Messages messages;
#Inject
private JavaScriptSupport javaScriptSupport;
void afterRender() {
javaScriptSupport.addInitializerCall("initMenu", new JSONObject()
put("option1", messages.get("option1"))
);
}
}
menu.js
(function( $, window ) {
'use scrict';
$.extend(Tapestry.Initializer, {
initMenu: function (spec) {
var currentOption=$('#activemenu').attr('name');
if (currentOption=="menu"){
$("#button1txt").text(spec.option1);
}
}
}
})(jQuery, window);

Related

How to keep script in partial view from loading more than once and causing errors when partial is used more than once in the same page

Working in ASP.NET MVC, I created a partial view which is rendered on the same page 2 times. My problem is the JavaScript is included as many times as the partial view is and JavaScript does not like classes to be redefined.
My question is: How do I include the JavaScript in the partial view so it remains modular, but only have it included in the page once? I am not interested in solutions which require including the .js file separately from the content of the partial view, like
<script src="some.js"></script>
#Html.Partial("some/partial.cshtml")
#Html.Partial("some/partial.cshtml")
but I am okay with a separate .js file that is included inside the partial view. The partial view should include within it everything that is needed to make it work.
My code is structured something like this:
<div id=#ViewBag.id></div>
<script>
class MyClass{
constructor(divName){
this._divId = divId;
}
doSomething(){
/* do stuff with element that has id of divId */
}
}
</script>
Then, in the calling file, I have
<body>
#Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_1"} })
#Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_2"} })
</body>
<script>
$().ready(function(){
id1Functionality = new MyClass("id_1"); // please forgive the poor naming :-)
id2Functionality = new MyClass("id_2");
id1Functionality.doSomething();
id2Functionality.doSomething();
})
</script>
One solution is to implement an Html helper extension function which will only load a script once. See below. (this can work for CSS and other included files, too).
Implement an extension for the HtmlHelper class and a private backing class as a singleton per HttpContext.
public static class YourHtmlHelperExtensionClass
{
private class TagSrcAttrTracker
{
private TagSrcAttrTracker() { }
public Dictionary<string, string> sources { get; } = new Dictionary<string, string>();
public static TagSrcAttrTrackerInstance {
get {
IDictionary items = HttpContext.Current.Items;
const string instanceName = "YourClassInstanceNameMakeSureItIsUniqueInThisDictionary";
if(!items.Contains(instanceName))
items[instanceName] = new TagSrcAttrTracker();
return items[instanceName] as TagSrcAttrTracker;
}
}
}
public static MvcHtmlString IncludeScriptOnlyOnce(this HtmlHelper helper, string urlOfScript)
{
if(TagSrcAttrTracker.Instance.sources.ContainsKey(urlOfScript))
return null;
TagSrcAttrTracker.Instance.sources[urlOfScript] = urlOfScript;
TagBuilder script = new TagBuilder("script");
scriptTag.MergeAttribute("src", urlOfScript);
return MvcHtmlString.Create(script.ToString());
}
}
Then, separate the JavaScript and other code into separate files.
Example .js file contents
class MyClass{
myFunction() {
constructor(divId){
this._divId = divId
}
doSomething() {
// do something with a div with id == divId
}
}
}
Example .cshtml file contents for partial view
<link rel="stylesheet" type="text/css" href="~/Content/CustomCSS/MyPartialView.css"/>
<div id="#ViewBag.id">
Some content! Yay!
</div>
#Html.IncludeScriptOnlyOnce("/Scripts/CustomScripts/MyPartialView.js")
Example .cshtml file that consumes the partial view
...
<body>
<h1>Here is some content!</h1>
#Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_1"} })
#Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_2"} })
#Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_3"} })
</body>
<script>
$().ready(
const id1Functionality = new MyClass("id_1") // forgive the poor naming :-)
const id2Functionality = new MyClass("id_3")
const id3Functionality = new MyClass("id_2")
id1Functionality.doSomething();
id2Functionality.doSomething();
id3Functionality.doSomething();
)
</script>
The partial view may have been included more than once and the JavaScript is packaged with the partial view, but the .js file is only included in the page once, hence no complaining by the browser that MyClass was declared more than once.

Failed to load resource: the http://website.azurewebsites.net/signalr/hubs server responded with a status of 404 (Not Found)

My MVC-5 Azure-hosted Web App (VS 2013 / VB) using SignalR technology seems to not be creating the necessary SignalR/hubs JavaScript page.
Here's all the details:
First, since I believe that Azure will not allow for the creation of the /signalr/hubs source page, I 'stole' a sample hub page from my own SignalR test app. I then added a signalr.js file into Scripts/Custom folder of my web app. Here's the JavaScript file:
(function ($, window, undefined) {
/// <param name="$" type="jQuery" />
"use strict";
if (typeof ($.signalR) !== "function") {
throw new Error("SignalR: SignalR is not loaded. Please ensure jquery.signalR-x.js is referenced before ~/signalr/js.");
}
var signalR = $.signalR;
function makeProxyCallback(hub, callback) {
return function () {
// Call the client hub method
callback.apply(hub, $.makeArray(arguments));
};
}
function registerHubProxies(instance, shouldSubscribe) {
var key, hub, memberKey, memberValue, subscriptionMethod;
for (key in instance) {
if (instance.hasOwnProperty(key)) {
hub = instance[key];
if (!(hub.hubName)) {
// Not a client hub
continue;
}
if (shouldSubscribe) {
// We want to subscribe to the hub events
subscriptionMethod = hub.on;
} else {
// We want to unsubscribe from the hub events
subscriptionMethod = hub.off;
}
// Loop through all members on the hub and find client hub functions to subscribe/unsubscribe
for (memberKey in hub.client) {
if (hub.client.hasOwnProperty(memberKey)) {
memberValue = hub.client[memberKey];
if (!$.isFunction(memberValue)) {
// Not a client hub function
continue;
}
subscriptionMethod.call(hub, memberKey, makeProxyCallback(hub, memberValue));
}
}
}
}
}
$.hubConnection.prototype.createHubProxies = function () {
var proxies = {};
this.starting(function () {
// Register the hub proxies as subscribed
// (instance, shouldSubscribe)
registerHubProxies(proxies, true);
this._registerSubscribedHubs();
}).disconnected(function () {
// Unsubscribe all hub proxies when we "disconnect". This is to ensure that we do not re-add functional call backs.
// (instance, shouldSubscribe)
registerHubProxies(proxies, false);
});
proxies['bpHub'] = this.createHubProxy('bpHub');
proxies['bpHub'].client = {};
proxies['bpHub'].server = {
begin: function () {
return proxies['bpHub'].invoke.apply(proxies['bpHub'], $.merge(["new"], $.makeArray(arguments)));
},
hello: function () {
return proxies['bpHub'].invoke.apply(proxies['bpHub'], $.merge(["send"], $.makeArray(arguments)));
},
helloServer: function () {
return proxies['bpHub'].invoke.apply(proxies['bpHub'], $.merge(["broadcast"], $.makeArray(arguments)));
}
};
return proxies;
};
signalR.hub = $.hubConnection("/signalr", { useDefaultPath: false });
$.extend(signalR, signalR.hub.createHubProxies());
}(window.jQuery, window));
Now, I know that the proxies map to functions in classes that I set up. But I'm not quite sure EXACTLY how to do this, given my very large app. In essence, I've simply added some classes to the project, so they are in the root folder. And then in the Startup.vb file, I do this;
Imports Microsoft.Owin
Imports Owin
Imports Microsoft.AspNet.SignalR
<Assembly: OwinStartup(GetType(Startup))>
Public Class Startup
Public Sub Configuration(app As IAppBuilder)
Dim cn As String = ConfigurationManager.ConnectionStrings("AzureServiceBus").ConnectionString
GlobalHost.DependencyResolver.UseServiceBus(cn, "dtxEarth3")
app.MapSignalR()
End Sub
End Class
Then, per the book called SignalR Real-Time Application Cookbook by Roberto Vespa, I added the following classes to the root folder of my app;
sigRmb.vb;
Imports System.Collections.Generic
Imports System.Threading.Tasks
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Client
Imports Microsoft.AspNet.SignalR.Messaging
Imports Microsoft.AspNet.SignalR.Hubs
<HubName("bpHub")>
Public Class SignalRBackplaneMessageBus
Inherits ScaleoutMessageBus
Private ReadOnly _connection As HubConnection
Private ReadOnly _hub As IHubProxy
Public Sub New(dependencyResolver As IDependencyResolver, configuration As SignalRBackplaneConfiguration)
MyBase.New(dependencyResolver, configuration)
_connection = New HubConnection(configuration.EndpointAddress)
_hub = _connection.CreateHubProxy("bpHub")
_hub.[On](Of Byte())("broadcast", Function(m)
Dim message = SignalRBackplaneMessage.FromBytes(m)
OnReceived(0, message.Id, message.ScaleoutMessage)
End Function)
_connection.Start().Wait()
End Sub
Protected Overrides Function Send(streamIndex As Integer, messages As IList(Of Message)) As Task
Return Send(messages)
End Function
Protected Overrides Function Send(messages As IList(Of Message)) As Task
If _connection.State <> ConnectionState.Connected Then
Return Task.FromResult(False)
End If
Dim newId = _hub.Invoke(Of Long)("GetId").Result
Dim data = SignalRBackplaneMessage.ToBytes(newId, messages)
Return _hub.Invoke("Publish", data)
End Function
End Class
sigRconfig;
Imports Microsoft.AspNet.SignalR.Messaging
Public Class SignalRBackplaneConfiguration
Inherits ScaleoutConfiguration
Private m_EndpointAddress As String = "Endpoint=sb://dtxdrill-ns.servicebus.windows.net/;SharedAccessKeyName=RigMon100;SharedAccessKey=U7/6C+1y1kExpCMVgG+1tZpvz6um/d4NOiucComR/CU="
Public Property EndpointAddress() As String
Get
Return m_EndpointAddress
End Get
Set(value As String)
m_EndpointAddress = value
End Set
End Property
End Class
sigRbm;
Imports System.Collections.Generic
Imports System.IO
Imports Microsoft.AspNet.SignalR.Messaging
Public Class SignalRBackplaneMessage
Private m_Id As ULong
Private m_ScaleoutMessage As ScaleoutMessage
Public Property Id() As ULong
Get
Return m_Id
End Get
Private Set(value As ULong)
m_Id = value
End Set
End Property
Public Property ScaleoutMessage() As ScaleoutMessage
Get
Return m_ScaleoutMessage
End Get
Private Set(value As ScaleoutMessage)
m_ScaleoutMessage = value
End Set
End Property
Public Shared Function ToBytes(id As Long, messages As IList(Of Message)) As Byte()
If messages Is Nothing Then
Throw New ArgumentNullException("messages")
End If
Using ms = New MemoryStream()
Dim binaryWriter = New BinaryWriter(ms)
Dim scaleoutMessage = New ScaleoutMessage(messages)
Dim buffer = scaleoutMessage.ToBytes()
binaryWriter.Write(id)
binaryWriter.Write(buffer.Length)
binaryWriter.Write(buffer)
Return ms.ToArray()
End Using
End Function
Public Shared Function FromBytes(data As Byte()) As SignalRBackplaneMessage
Using stream = New MemoryStream(data)
Dim binaryReader = New BinaryReader(stream)
Dim id = CULng(binaryReader.ReadInt64())
Dim count = binaryReader.ReadInt32()
Dim buffer = binaryReader.ReadBytes(count)
Return New SignalRBackplaneMessage() With { _
.Id = id, _
.ScaleoutMessage = ScaleoutMessage.FromBytes(buffer) _
}
End Using
End Function
End Class
And this one, called sigR_DependencyResolverExtensions.vb;
Imports System.Runtime.CompilerServices
Imports Microsoft.AspNet.SignalR
Imports Microsoft.AspNet.SignalR.Messaging
Module sigR_DependencyResolverExtensions
<System.Runtime.CompilerServices.Extension> _
Public Sub UseSignalRBackplane(resolver As IDependencyResolver, endpointAddress As String)
resolver.UseSignalRBackplane(New SignalRBackplaneConfiguration() With { _
.EndpointAddress = endpointAddress _
})
End Sub
<System.Runtime.CompilerServices.Extension> _
Public Sub UseSignalRBackplane(resolver As IDependencyResolver, configuration As SignalRBackplaneConfiguration)
resolver.Register(GetType(IMessageBus), Function() New SignalRBackplaneMessageBus(resolver, configuration))
End Sub
End Module
And finally, for my view, I have;
#Code
Layout = Nothing
End Code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Drillers Readout - HTI Job ##ViewBag.JobNumber</title>
<style>
#messages li {
list-style-type: none;
}
</style>
#Styles.Render("~/Content/css")
#Styles.Render("~/Content/themes/base/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#Scripts.Render("~/bundles/jqueryui")
#Scripts.Render("~/bundles/signalR")
<script src="~/Scripts/jquery.signalR-2.2.1.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="~/Scripts/Custom/signalr.js"></script>
<script type="text/javascript">
$(function () {
//var cn = $.hubConnection();
$.connection.hub.url = "#Url.Content("~/Scripts/Custom/signalr.js")";
var hub = $.connection.bpHub;
$.connection.hub.start().done(function() {
alert('okay 1');
})
.fail(function(e) {
alert('uh-oh! Connection Error ' + e);
});
//var myProxy = cn.createHubProxy('bpHub');
//var backplane = cn.backplane;
//myProxy.on('broadcast', function (message) {
// $('#messages').prepend($('<li/>').text(message));
//});
//cn.start().done(function () {
// myProxy.invoke('new');
//})
});
</script>
</head>
<body>
#*<span id="newTime"></span><br />
<input type="button" id="btnClick" value="Send Message" /><br />
<span id="message"></span>*#
<ul id="messages"></ul>
</body>
</html>
But when I run it, I get (in Chrome);
http://mywebsite.azurewebsites.net/Scripts/Custom/signalr.js/negotiate?clientProtocol=1.5&connectionData=...
Failed to load resource: the server responded with a status of 404...
I know I've got several things wrong with my code, including setting up the signalr.js file, among other things. Please help.
Does your SignalR application work on your local environment? Or it only does not work in Azure side? For general 404 issue, please mark sure your have a call to MapHubs() in Global.asax, and make sure that the Hub route is registered before any other routes in your application. Reference the JavaScript file with #Url.Content, assuming you're using ASP.NET MVC3.
<script type="text/javascript" src="#Url.Content("~/signalr/hubs")"></script>
In ASP.NET MVC 4 you can do the following:
<script type="text/javascript" src="~/signalr/hubs"></script>
See the SignalR FAQ on GitHub
If this is Azure side issue, Please make sure the SignalR related files has been uploaded to Azure side via KUDU tool. In addition, please also check whether websocket is enabled via this article.

Yahoo.extend in alfresco for extending dnd-upload component

I would like to customize the dnd-upload.js file. For example I want to override _adjustGuiIfFinished method. I've tried several times to do it, but all of them failed (I was using some tutorials/examples:
http://blogs.alfresco.com/wp/wabson/2011/08/12/custom-admin-console-components-in-share/
https://forums.alfresco.com/forum/developer-discussions/alfresco-share-development/javascrip-autocompete-yahoo-library-03152012)
Here are my steps:
create .js file, let's say dnd-upload-ep.js with following contents:
(function ()
{
Alfresco.EpDNDUpload = function Alfresco_EpDNDUpload(htmlId)
{
Alfresco.EpDNDUpload.superclass.constructor.call(this, htmlId);
return this;
};
YAHOO.extend(Alfresco.EpDNDUpload, Alfresco.DNDUpload,{
_adjustGuiIfFinished: function EpDNDUpload_adjustGuiIfFinished()
{
...
// function body with some modifications
...
})
});
include just created file in .ftl. Override dnd-upload.get.html.ftl and include file in js dependencies:
...
<#markup id="js">
<#-- JavaScript Dependencies -->
<#script type="text/javascript" src="${url.context}/res/components/upload/dnd-upload.js" group="upload"/>
<#script type="text/javascript" src="${url.context}/res/components/upload/dnd-upload-ep.js" group="upload"/>
</#>
...
instead of original DNDUpload instantiate recently created EpDNDUpload. To do it override dnd-upload.get.js changing 'Widget instantiation metadata':
...
//Widget instantiation metadata...
var dndUpload = {
id : "EpDNDUpload",
name : "Alfresco.EpDNDUpload",
assignTo : "dndUpload"
};
model.widgets = [dndUpload];
...
Seems that it should work, but it doesn't. When I upload document I got error that Alfresco.EpDNDUpload not created and could't be instantiated.
Is there is something I do wrong?

separate views in different files while structuring jquery binds for large websites

I am trying to implement this way to structure my jquery binds, it worked perfect.
I just have one question:
In the sample in the article he put all the views in one namespace called SITENAME, and like that all views should exist in one .js file, how can I put the views in different .js files?
for example:
To put common view in common.js file and users view in users.js
Namespace SITENAME is just a JavaScript object.
If you have code like this:
SITENAME = {
common: { ... },
example1: { ... },
example2: { ... }
}
You can change it to:
SITENAME = {
common: { ... }
};
SITENAME.example1 = { ... };
SITENAME.example2 = { ... };
As you can see now the example1 and example2 objects are still defined inside SITENAME, but they are separated from the definition of SITENAME object itself.
So in your case you need to create your "namespace" object first (e.g. create app.js which will contain also some configuration stuff) and then you create separate .js files that will define own properties on already existing SITENAME object.
Example:
HTML:
...
<head>
...
<script src="js/app.js" />
<script src="js/example1.js" />
<script src="js/example2.js" />
</head>
...
app.js (insert here common functionality, configuration, etc):
App = { ... };
example1.js:
App.example1 = { ... };
example2.js:
App.example2 = { ... };

Asp.net mvc passing a C# object to Javascript

I have c# class say options more like AjaxOptions.
public class options
{
public string Url {get;set;}
public string httpMethod {get;set}
}
and a javascript function like this
function dosomething(obj)
{
if (obj.Url!="" and obj.HttpMethod=="something")
loadsomething();
}
Now in my Controller action
public class mycontroller : controller
{
public ActionResult WhatToDo()
{
options obj = new options{Url="someurl"};
return PartialView(obj);
}
}
in my view I need this object kind of string which i should be able to pass to my method.
#model options
<script>
dosomething(#model.SomeFunctionToConverToString())
</script>
So I need this SomeFunctionToConverToString method which i will convert this object to string.
Thanks
You should be able to use it like you would any other output of a model property in your view. Just reference the property that you want to pass in the JS function.
#model options
<script>
dosomething('#(model.Url)');
</script>
See this post for more information on using Razor inside of JS
EDIT - Something that might catch you is that if your URL get's broken from the HTML encoding that Razor does using the above, you can use the #Html.Raw() function which will pass the Url property without HTML encoding it.
<script>
dosomething('#Html.Raw(model.Url)');
</script>
EDIT 2 - And another SO post to the rescue! You are going to most likely want to convert your model to JSON in order to use in a Javascript function. So...in order to do that - you will need something in your view model to handle a JSON object.
public class optionsViewModel
{
public options Options{get;set;}
public string JsonData{get;set;}
}
and in your controller:
public class mycontroller : controller
{
public ActionResult WhatToDo()
{
options obj = new options{Url="someurl"};
var myViewModel = new optionsViewModel;
myViewModel.options = obj;
var serializer = new JavaScriptSerializer();
myViewModel.JsonData = serializer.Serialize(data);
return PartialView(myViewModel);
}
}
And finally the view:
#model optionsViewModel
<script>
dosomething('#model.JsonData')
</script>
Using this method, then your function will work as expected:
function dosomething(obj)
{
if (obj.Url!="" and obj.HttpMethod=="something")
loadsomething();
}
EDIT 3 Potentially the simplest way yet? Same premise as edit 2, however this is using the View to JsonEncode the model. There are probably some good arguments on either side whether this should be done in the view, controller, or repository/service layer. However, for doing the conversion in the view...
#model options
<script>
dosomething('#Html.Raw(Json.Encode(Model))');
</script>
Try this:
<script type="text/javascript">
var obj= #Html.Raw(Json.Encode(Model));
function dosomething(obj){}
</script>
That's work for me
Client side:
function GoWild(jsonData)
{
alert(jsonData);
}
Alert print :
{"wildDetails":{"Name":"Al","Id":1}}
MVC Razor Side:
#{var serializer new System.Web.Script.Serialization.JavaScriptSerializer();}
<div onclick="GoWild('#serializer.Serialize(Model.wildDetails)')"> Serialize It </div>
there is also a syntax error
<script type="text/javascript">
dosomething("#Model.Stringify()");
</script>
note the quotes around #Model.Stringify() are for javascript, so the emitted HTML will be:
<script type="text/javascript">
dosomething("this model has been stringified!");
</script>
I would recommend you have a look at SignalR, it allows for server triggered javascript callbacks.
See Scott H site for details: http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx
In summary thou ...
Javascript Client:
var chat = $.connection.chat;
chat.name = prompt("What's your name?", "");
chat.receive = function(name, message){
$("#messages").append("
"+name+": "+message);
}
$("#send-button").click(function(){
chat.distribute($("#text-input").val());
});
Server:
public class Chat : Hub {
public void Distribute(string message) {
Clients.receive(Caller.name, message);
}
}
So .. Clients.receive in C# ends up triggering the chat.receive function in javascript.
It's also available via NuGet.

Categories