I've followed the steps in this article to create a basic custom editor but I'm getting a 404 error when trying to enter Forms Edit mode from
/EPiServer/CMS/1.0.456/ClientResources/dtk/app/editors/EmailTextbox.js
The document linked article states that EPiServer automatically adds a mapping from /ClinetResources/Scripts to the app namespace. I took a punt and added a module.config to the root of my site, like so:
<?xml version="1.0" encoding="utf-8"?>
<module>
<assemblies>
<!-- This adds the Alloy template assembly to the "default module" -->
<add assembly="PropertyTest" />
</assemblies>
<dojoModules>
<!-- Add a mapping from alloy to ~/ClientResources/Scripts to the dojo loader configuration -->
<add name="app" path="Scripts" />
</dojoModules>
</module>
This fixed the 404 but now I get a type error in the console when I try to enter forms mode
TypeError {} dojo.js:15
(anonymous function) dojo.js:15
dojo.Deferred.reject.errback dojo.js:15
_174 dojo.js:15
dojo.Deferred._171.then.then dojo.js:15
dojo.Deferred.when.dojo.when dojo.js:15
dojo.declare._createInternal widgets.js:2
(anonymous function) widgets.js:2
_388 dojo.js:15
map dojo.js:15
dojo.declare._createWidgets widgets.js:2
(anonymous function) widgets.js:2
_388 dojo.js:15
_c6 dojo.js:15
_36 dojo.js:15
_7a dojo.js:15
_ee dojo.js:15
req.injectUrl._109 dojo.js:15
Why is this erroring?
The source of my JS file is as per the linked article but I've included below for completeness.
define([
// Inherited mixins
"dojo",
"dojo/_base/declare",
"dijit/_Widget",
"dijit/_TemplatedMixin"
], function (
dojo,
declare,
_Widget,
_TemplatedMixin) {
declare("app.editors.EmailTextbox", [_Widget, _TemplatedMixin], {
// templateString: [protected] String
// A string that represents the default widget template.
templateString: '<div> \
<input type="email" data-dojo-attach-point="email" data-dojo-attach-event="onchange:_onChange" /> \
</div>',
postCreate: function () {
// summary:
// Set the value to the textbox after the DOM fragment is created.
// tags:
// protected
this.set('value', this.value);
if (this.intermediateChanges) {
this.connect(this.email, 'onkeydown', this._onIntermediateChange);
this.connect(this.email, 'onkeyup', this._onIntermediateChange);
}
},
focus: function () {
// summary:
// Put focus on this widget.
// tags:
// public
dijit.focus(this.email);
},
isValid: function () {
// summary:
// Indicates whether the current value is valid.
// tags:
// public
var emailRegex = '[a-zA-Z0-9_.-]+#[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+';
if (!this.required) {
emailRegex = '(' + emailRegex + ')?';
}
var regex = new RegExp('^' + emailRegex + '$');
return regex.test(this.value);
},
onChange: function (value) {
// summary:
// Called when the value in the widget changes.
// tags:
// public callback
},
_onIntermediateChange: function (event) {
// summary:
// Handles the textbox key press events event and populates this to the onChange method.
// tags:
// private
if (this.intermediateChanges) {
this._set('value', event.target.value);
this.onChange(this.value);
}
},
_onChange: function (event) {
// summary:
// Handles the textbox change event and populates this to the onChange method.
// tags:
// private
this._set('value', event.target.value);
this.onChange(this.value);
},
_setValueAttr: function (value) {
// summary:
// Sets the value of the widget to "value" and updates the value displayed in the textbox.
// tags:
// private
this._set('value', value);
this.email.value = this.value || '';
}
});
});
If you've gotten your script to load properly then it's a good idea to deploy the debug versions of the script files. Head over to Debugging EPiServer CMS client side files for the download and instructions on how to deploy them.
With the compressed and minified versions it's very hard to figure out what's going wrong.
Are you aware that you can just use the RegularExpression attribute if you want email validation ?
[RegularExpression(EPiServer.Framework.Validator.EmailRegexString)]
public virtual string Email { get; set; }
If this occurs on a development box the solution is to disable the Broswer Link in Visual Studio.
http://www.herlitz.nu/2016/09/19/cant-load-the-episerver-edit-gui-in-development-environment/
Related
right now I am passing hard coded value for my name.
I am trying to pass the dynamic username for my name key inside my scriprt tag from sportsService.
its working fine in my ts file.
but its not working fine in my html file.
I am getting an error. ---> Uncaught TypeError: Cannot read property 'marksSession' of undefined
can you guys tell me how to pass inside script tag of .html.
providing my code below
index.html
<script>
(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/APP_ID';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()
</script>
<script>
let players=this.sportsService.marksSession();
console.log("players--->" + players);
if(players) {
this.userId = players.user_players.SSO[0];
}
Intercom('trackEvent', 'share-link');
window.intercomSettings = {
app_id: 'APP_ID',
name: "Jane Doe", // Full name
email: "customer#example.com", // Email address
created_at: 1312182000 // Signup date as a Unix timestamp
};
</script>
sports.ts
import { sportsService } from '../../services/sports.service';
constructor(public sportsService : sportsService){
}
ngOnInit() {
let that =this;
let players=this.sportsService.marksSession();
if(players) {
this.userId = players.user_players.SSO[0];
}
}
If you import your TypeScript file on your HTML page, that should take care of the TypeError you're getting. I believe you will need to compile your TypeScript to JavaScript prior to doing this.
Check out W3Schools for some info on how to use the tag in your HTML:
https://www.w3schools.com/tags/att_script_src.asp
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.
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?
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);
<h:commandLink id="#{id}" value="#{value}" action="#{actionBean.getAction}" onclick="alert(this);"/>
In the previous simplified example, the 'this' keyword used in the Javascript function won't reference the generated A HREF element, but will reference to the global window, because JSF generates the following (simplified) code:
<a onclick="var a=function(){alert(this)};var b=function(){if(typeof jsfcljs == 'function'){jsfcljs(document.forms['mainForm'],'generatedId,action,action','');}return false};return (a()==false) ? false : b();" href="#" id="generatedId">text</a>
So because JSF wraps the user defined onclick in a function, this will point to the global window. I don't have access to the id of the element because my code is used in a generic component that can be used in loops etc. and I don't use backing beans (Facelets + JSF).
So my question is, is there a way to access the A HREF element from within my onclick javascript function, without knowing the id?
EDIT:
Go here for a small library/sample code for getting the clientId from the id: JSF: working with component IDs
The HTML ID emitted by JSF controls is namespaced to avoid collisions (e.g. the control is a child of UIData and emitted multiple times, or the container is a portlet so the view can be rendered multiple times in one HTML page). This ID is known as the clientId, and is distinct from the ID set on the JSF control.
If you want to emit the clientId in the view, you can use a managed bean to do it.
public class JavaScriptBean {
public String getOnclickButton1() {
String id = "button1";
String clientId = getClientId(id);
return "alert('You clicked element id=" + clientId + "');";
}
public String getOnclickButton2() {
String id = "button2";
String clientId = getClientId(id);
return clientId;
}
private String getClientId(String id) {
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot view = context.getViewRoot();
UIComponent component = find(view, id);
return component.getClientId(context);
}
private UIComponent find(UIComponent component, String id) {
if (id.equals(component.getId())) {
return component;
}
Iterator<UIComponent> kids = component.getFacetsAndChildren();
while (kids.hasNext()) {
UIComponent kid = kids.next();
UIComponent found = find(kid, id);
if (found == null) {
continue;
}
return found;
}
return null;
}
}
This is configured in the application's faces-config.xml and bound to the view using the expression language:
<f:view>
<h:form>
<h:commandButton id="button1" value="b1"
onclick="#{javaScriptBean.onclickButton1}" />
<h:commandButton id="button2" value="b2"
onclick="alert('You clicked element id=#{javaScriptBean.onclickButton2}');" />
</h:form>
</f:view>
var a=function(){alert(this)};var b=function(){if(typeof jsfcljs == 'function'){jsfcljs(document.forms['mainForm'],'generatedId,action,action','');}return false};return (a()==false) ? false : b();
Oh dear lord! That's violently horrible.
And no, it appears to be throwing away 'this' before you get a chance to look at it - it should have said "return (a.call(this)==false)? false : b()".
On IE only you could read the srcElement from window.event, but that's pretty ugly.
How about avoiding JSF's weird event mangling entirely, by using unobtrusive scripting? eg. omit the onclick and say:
document.getElementById('generatedId').onclick= function() {
alert(this);
return false; // if you want to not follow the link
}
If you need the link to continue into JSF's event handling, you'd have to save the old onclick event handler and call it at the end of the function, or use Element.addEventListener (attachEvent on IE) to put your scripting hooks in at an earlier stage than the onclick.
<head>
..
<script type="text/javascript">
var myCommandLinkId = "undefined";
</script>
..
</head>
..
<h:commandLink id="myCommandLink" value="Click Me" onmousedown="myCommandLinkId=this.id;" onclick="alert(myCommandLinkId);" />