Sitecore SPEAK and Javascript - javascript

I am trying to replicate what is shown in this video series by Jakob:
I am able to get everything work except the custom Javascript part.
define(["sitecore"], function (Sitecore) {
var ListPage = Sitecore.Definitions.App.extend({
initialized: function () {
alert('Test');
}
});
return ListPage;
});
I even tried to fire Sitecore.app command in sc_debug mode but that is returning "undefined"

if your in Sitecore 7.5 or 8 the app has been moved to Sitecore.Speak.app rather than Sitecore.app

I believe you have to add a js script file to your Page Code control.
On the Page Code Control there is field called PageCodeScriptFileName you can add a path to your custom js file there. Then you can add your code above in that js file.
There's more info on this blog post from Martina:
http://mhwelander.net/2014/07/01/speak-for-newbies-part-4-pagecode-and-javascript-libraries/

Related

Calling an external js function as ejs onclick event

I have a nodejs application that renders an ejs file called main.ejs including a button.
I'd like to declare a function in an external javascript file that I can call it in the onclick event of that button(in main.ejs).
But every time I run the app, by rendering the page, that function will be called automatically, but when I click on the button it won't be called!
(I need to mention that I have already tried writing this function directly in main.ejs in a script tag, and it perfectly works. But I'm persisting in moving it to a respective js file)
functions.js (the external js file)
function optionClick() {
console.log("Yoohooo!!");
}
module.exports = {
optionClickFunc: optionClick
};
server.js
var functions = require('./public/functions');
app.get('/question', (req, res) => {
res.render('main.ejs', {
data: {
function: functions.optionClickFunc
}
});
});
main.ejs
<button id="submit-button" onclick="'<%= data.function() %>';"> START </button>
And whenever I have this url in my browser: http://localhost:3000/question, I see the log message("Yoohooo!!") printed in the console without clicking on the button!
While it doesn't print the message when I click the botton!!
Any idea? I really appreciate your time.
data.function is a function and when you call it in your server-side-code, you call it in your server side code.
When you write HTML you need to write strings and the string representing the value of the onclick attribute needs to be JavaScript source code. (data.function, as mentioned, is a function not a string of source code.) The client will compile that source code and execute it.
Your server-side and client-side code might both be written in JavaScript, but they are two different programs running in two different environments (Node.js and the browser) which will usually (less so during development) run on two different computers.
Related: What is the difference between client-side and server-side programming?

SmartAdmin Template Pagefunction runs twice Bug

I am developing web application in smartAdmin Template, which is fully ajax based template you can check demo here. i am facing some difficulties in this template. when i write one javascript function on some page it works on all pages.
for example
$(document).on('click', '#elementA', function(){
alert('Hello World');
});
works on other pages's element which also have same id, it is difficult to give different ids to all element as it is very large project and i am working on it since 6 months, so i thought about it and find out solution to give unique id to each pages and write script like this.
$(document).on('click', '#pageA #elementA', function(){
alert('Hello World');
});
i thought i solved the issue but, isn't function stopped working on other page's element. but when i visit #PageA 2nd time the function runs twice. actually template stores all the user defined function in local memory storage (i think, i am not sure about this) and keeps storing, until we do not refresh whole template.
ok, after long R&D i solved this my self..
i used loadscript() function to prevent loading scripts twice unnecessarily..
i wrote all the script into one file (now i will have two view pages for one page.)
earlier it was like..
A.php -> JScript + PHP & HTML
now it is like A.php -> PHP & HTML, script/A.php -> OnlyJS
as i am using codeginiter framework, and dont want others too see js by accessing it through url, i used this process.
code on my view file
loadScript("<?php echo site_url('processor/load_script/path_to_folder/script/add'); ?>");
function on Processor controller
public function load_script($path)
{
$last_segment = count($this->uri->segment_array());
$path = '';
for($i=3;$i<=$last_segment;$i++)
{
$path .= '/'.$this->uri->segment($i);
}
$this->load->view('core/ajax'.$path);
}

How to do client-side UI events in Blazor

I just started playing around with Blazor and I can already see the great potential of this new framework.
I'm wondering, though, how it will handle doing simple things like setting focus on an input control? For instance, after I handle a click event, I want to set the focus to a text input control. Do I have to use JQuery for something like that, or will Blazor have some built-in methods for that sort of thing?
Thanks
Update: I posted an answer below with an example of how to set the focus to a control by invoking a JavaScript function from the .Net code.
As of right now (Blazor 0.9.0) you create your JavaScript functions in the Index.html (or reference them from Index.html) and then in your Blazor page or component you call JsRuntime.InvokeAsync("functionName", parms);
https://learn.microsoft.com/en-us/aspnet/core/razor-components/javascript-interop
Blazor is just the replacement (to be more precise "value addition") to JavaScript. It is a client-side only solution (but it might add some easy binding to ASP.NET in the future).
Still, it's completely based on HTML and CSS. C# is replacing the JS part using web assembly. So nothing has changed on how you access / modify HTML controls.
As of now (version 0.1.0) you have to rely on HTML DOM focus() Method to do what you intend to do (yes you have to use JavaScript as of now :( ).
// Not tested code
// This is JavaScript.
// Put this inside the index.html. Just below <script type="blazor-boot"></script>
<script>
Blazor.registerFunction('Focus', (controlId) => {
return document.getElementById(controlId).focus();
});
</script>
//and then wrap it for calls from .NET:
// This is C#
public static object Focus(string controlId)
{
return RegisteredFunction.Invoke<object>("Focus", controlId);
//object type is used since Invoke does not have a overload for void methods. Don't know why.
//this will return undefined according to js specs
}
For more information, you can refer to below.
If you want to improve the packaging of JS neatly, you can do something like this:
https://stackoverflow.com/a/49521216/476609
public class BlazorExtensionScripts : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
builder.OpenElement(0, "script");
builder.AddContent(1, "Blazor.registerFunction('Focus', (controlId) => { document.getElementById(controlId).focus(); });");
builder.CloseElement();
}
public static void Focus(string controlId)
{
RegisteredFunction.Invoke<object>("Focus", controlId);
}
}
then add this component to the root: (App.cshtml):
<BlazorExtensionScripts></BlazorExtensionScripts>
<Router AppAssembly=typeof(Program).Assembly />
I want to add a more up-to-date (as of 0.9.0) example of calling a JavaScript function to set the focus to another control after some event, like clicking on a button. This might be helpful for someone just starting out with Blazor (like me).
This example builds on the example code in the Blazor documentation "Build Your First Blazor Components App" at https://learn.microsoft.com/en-us/aspnet/core/tutorials/build-your-first-razor-components-app?view=aspnetcore-3.0
First, follow all the instructions in the documentation. When you have a working To-Do List page, then add the following:
At the bottom of Index.html, under wwwroot, and below the script tag that loads the webassembly.js, add the following script:
<script>
window.MySetFocus = (ctrl) => {
document.getElementById(ctrl).focus();
return true;
}
</script>
At the top of your todo.cshtml page, add the following using statement:
#inject IJSRuntime JsRuntime;
In the #functions section of your todo.cshtml page, add the following function:
async void Focus(string controlId)
{
var obj = JsRuntime.InvokeAsync<string>(
"MySetFocus", controlId);
}
In the AddToDo() function, just below the line where you set the "newToDo" variable to an empty string, add a call to the Focus function, passing in the string id of the input control. (The example in the docs does not assign an ID to the input control, so just add one yourself. I named mine "todoItem").
void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
Focus("todoItem"); // this is the new code
}
}
Build and run your app. When you click the add new item button, the new item should be added to the list, the input control blanked out, and the focus should be back in the input control, ready for another item to be added.
From .NET 5 Preview 8
Set UI focus in Blazor apps
Blazor now has a FocusAsync convenience method on ElementReference for setting the UI focus on that element.
<button #onclick="() => textInput.FocusAsync()">Set focus</button>
<input #ref="textInput"/>
You can't directly call JavaScript function. You are required to first register your functions like,
<script>
Blazor.registerFunction('ShowControl', (item) => {
var txtInput = document.getElementById("txtValue");
txtInput.style.display = "";
txtInput.value = item;
txtInput.focus();
});
return true;
</script>
Then you need to declare a method in C# which calls this JavaScript function. Like,
private void CallJavaScript()
{
RegisteredFunction.Invoke<bool>("ShowControl", itemName);
}
You can call this C# method on click of button. Like,
<button id="btnShow" class="btn btn-primary" #onclick(CallJavaScript)>Show</button>
This post Create a CRUD App using Blazor and ASP.NET Core
shows a working demo of calling JavaScript from Blazor.

Where do I put onWindowBeforeUnload?

I have a SAP UI5 application and I would like to show a box that appears when the user tries to navigate away from the screen through methods outside my application (clicking on links, manually changing URL, etc).
I see there is a onWindowBeforeUnload() method but I am not sure where I put this method or how it gets called. I tried including it in my controller that I want the functionality in but it does not get called when I navigate away. If there's any other function that can provide this behavior, that'll be fine too.
Here's what I did in my controller:
onWindowBeforeUnload: function() {
alert("you sure?");
},
I see that this is a method of the component class but I thought this was created in the beginning; I am not too familiar with this concept.
I don't think you can override it directly from your controller. You'll either have to override it on the window object itself (as per #matt-spinks' answer above) or override it on your Component.js file (if you are using one).
Here's how to do it on the Component.js file:
sap.ui.define(["sap/ui/core/UIComponent"], function (UIComponent) {
"use strict";
return UIComponent.extend("company.main.Component", {
// ...
// ...
/**
* Fired before the window closes or moved to another URL
*/
onWindowBeforeUnload: function(oEvent) {
// your code
},
/**
* Fired when the window is closed.
*/
onWindowUnload: function(oEvent) {
// your code
}
});
});
There are a couple different ways of doing it:
in the body tag
<body onbeforeunload='alert("no!!")'>
in your js code:
<script>
window.onbeforeunload = function() {
alert('no!!');
}
</script>
Make sure to use window.onbeforeunload and not onWindowBeforeUnload.
Also, make sure you put the code within tags in the rendered output of your page, or inside an included javascript file. Based on what your code looks like, it sounds like you are using a javascript library, which is why you are using functionName: function(){ //body }. You cannot use that method to override the window.onbeforeunload function, because you are trying to handle the function inside a sub-node of window. You have to use the top-level window node and handle the function there. And you can do that by putting this code directly inside <script> tags or the body tag.

Using SnapEngage with Emberjs cause a JS error

As soon as I add:
<script src="/bower_components/ember/ember.min.js"></script>
on the same page where there's our snagengage chat code:
<!-- begin SnapEngage code -->
<script type="text/javascript">
(function() {
var se = document.createElement('script'); se.type = 'text/javascript'; se.async = true;
se.src = '//commondatastorage.googleapis.com/code.snapengage.com/js/4f645e9b-afb9-4226-9ebc-f8fc52d28cef.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(se, s);
})();
</script>
<!-- end SnapEngage code -->
it provokes an error:
Uncaught TypeError: Cannot call method 'push' of undefined 4f645e9b-afb9-4226-9ebc-f8fc52d28cef.js:223
YAHOO.register 4f645e9b-afb9-4226-9ebc-f8fc52d28cef.js:223
(anonymous function) 4f645e9b-afb9-4226-9ebc-f8fc52d28cef.js:242
Anyone ever experienced this? Any suggestion about how to fix this?
PS: I tried removing that JS line and it works, that's definitively a conflict between Ember and some YAHOO library I guess.
Thanks!
I opened a ticket on this with SnapEngage and they recently pushed out a fix. If you had a SnapEngage account prior to Mar 6, 2014, then you need to click "Save" within the "Style" section of your account in order for the JS to be updated to the latest version. After this, the error should go away - worked for me!
NOTE: I am using Ember 1.4.0
I had this same issue and I think it was caused by a _super() on the YAHOO.register function cycling through line 233 twice. The first time it does it the variables k.versions and k.builds are defined, but the second time they are not (perhaps because the super reruns the YAHOO.register function without passing in any arguments. Regardless of exactly what caused it, I was able to remedy the issue (albeit in a VERY hacky way) by making the following edits to the snapengage.js source:
1) On line 233 change:
k.versions.push(p);k.builds.push(q);
to:
k.versions ? k.versions.push(p):false;k.builds ? k.builds.push(q):false;
All this does is check to see if the variables are defined and if they are, push to them. If not, do nothing.
I placed the edited snapengage.js source file in app/assets/javascripts/vendor/ and then added the following line to my application.js file:
//= stub ./vendor/snapengage.js
This will stop your ember application from loading the SnapEngage source when the app loads.
Finally, I wrote a chat mixin and loaded the snapengage.js script as follows:
App.Chat = Em.Mixin.create({
agentOnline: false,
didInsertElement: function() {
this._getChatApi();
},
_getChatApi: function() {
var url = 'assets/home/vendor/snapengage.js',
_this = this;
$.getScript(url).done(function() {
// Your custom SnapEngage Javascript API code here. For example...
SnapEngage.getAgentStatusAsync(function(online) {
_this.set('agentOnline', online);
});
});
},
});
App.IndexView = Em.View.extend(Home.Chat, {
// The rest of your view code here
});
The snapengage.js script won't load itself twice but if you're using the mixin on multiple pages you might want to make sure you're not loading the chat assets (images, loading spinner, etc) twice because the plugin seems to make a call to snapengage.com everytime you click on the 'help' button rendered on the webpage.
As I mentioned, it's a very hacky solution and I don't recommend editing the source code for plugins, but this will give you a fix to easily use Snapengage in an Ember.js app.

Categories