Using WYSIWYG editor like summernote in openui5 application - sapui5

I am fairly new to openui5. I want to include summernote editor into my application. I have included the cdn links from their homepage but I am getting the following error
ShellRenderer-dbg.js:143 Uncaught (in promise) TypeError: Cannot read property 'require' of undefined
at Object.S.getLogoImageHtml (ShellRenderer-dbg.js:143)
at Object.S.render (ShellRenderer-dbg.js:86)
at R.renderControl (RenderManager-dbg.js:1004)
at R.render (RenderManager-dbg.js:1259)
at constructor.U.rerender (UIArea-dbg.js:629)
at constructor.Core.renderPendingUIUpdates (Core-dbg.js:2774)
at constructor.Core.init (Core-dbg.js:1235)
at Core-dbg.js:485
at a (Core-dbg.js:179)
at SyncPoint.finishTask (Core-dbg.js:173)
Any ideas would be much appreciated. Thanks

I've managed to get this working in a simple scenario but not sure how it will work with other UI5 elements & re-rendering etc. I've created a simple control to show how it could interact with UI5 but it would need some work!
Notes: SAPUI5 contains jQuery in the default library, although there is a non-jQuery version available so you can use your own version of jQuery, I am not sure of the version needed to get both working optimally overlap. Additionally, Summernote seems to require bootstrap CSS + JS and not sure if that will work with UI5 too, especially if this is to be deployed in a Launchpad scenario. Could be OK as a standalone app though!
Have fun!
sap.ui.define([
"sap/ui/core/Control"
], function (Control) {
"use strict";
return Control.extend("MySummernoteControl", {
metadata: {
properties: {},
aggregations: {},
events: {}
},
renderer: {
apiVersion: 2,
render: function(rm, oButton) {
rm.openStart("div", oButton);
rm.openEnd();
rm.close("div");
}
},
onAfterRendering: function () {
if (!this._rendered) {
this.$().summernote();
this._rendered = true;
}
}
});
});
const ctrl = new MySummernoteControl();
ctrl.placeAt("content");
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
<!-- include bootstrap -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<!-- include summernote css/js -->
<link href="https://cdn.jsdelivr.net/npm/summernote#0.8.18/dist/summernote.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote#0.8.18/dist/summernote.js"></script>
</head>
<body class="sapUiBody sapUiSizeCompact">
<div id='content'></div>
</body>
</html>

Related

swagger custom layout from scala-rho

I have a nice and simple API swagger standard layout documentation url, auto generated by the rho-routes swagger support. I want to customize the layout with let's say colors, logo, phrases and examples.
In my scala backend the SwaggerUI service is generated by this:
case GET -> Root =>
implicitly[Applicative[F]].pure(
Response[F]()
.withStatus(Status.SeeOther)
.withHeaders(Location(Uri.fromString(
s"${webjarPath}/swagger-ui/3.40.0/index.html?url=${swaggerApiJsonPath}&layout=BaseLayout").right.get)
)
)
}
Is it possible to customize this "BaseLayout" direclty from the backend without importing a React dependency? If not: can I redirect the whole thing on my website to customize it from a ReactJS repo? If yes, how? Do I need a swagger npm integration? I'm a backend dev and I'm not very solid on FE infrastructures matters.
I'd appreciate someone to pointing me some articles or solutions I can study and apply with this case. Thanks all
You serve a webjar which is easy to set up but difficult (if not impossible, I'm no expert) to customize.
What you can do to at least serve a customized Swagger UI, is handle it like any Play Twirl template:
add all the Swagger frontend resources needed in your project:
find the links in the /app/views/index.scala.html contents below. I have:
ls public/swagger-ui
swagger-ui-bundle.js swagger-ui.js
oauth2-redirect.html swagger-ui.css swagger-ui-standalone-preset.js
call the template from your controller:
See https://www.playframework.com/documentation/2.8.x/ScalaTemplates as well
def api: Action[AnyContent] =
Action { implicit request =>
Ok(views.html.index(s"https://${appConfig.apiUrl}", giveItSomeArgs)
}
customize your Swagger in the Twirl template:
mine is in /app/views/index.scala.html:
#import play.api.libs.json.JsValue
#import play.api.libs.json.Json
#(apiUrl: String, giveItSomeArgs: Set[String])
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="assets/swagger-ui/swagger-ui.css" >
<link rel="icon" type="image/png" href="../favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="../favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="assets/swagger-ui/swagger-ui-bundle.js"> </script>
<script src="assets/swagger-ui/swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "/assets/openapi.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl,
{
statePlugins: {
spec: {
wrapActions: {
updateJsonSpec: function(oriAction, system) {
return (spec) => {
// change spec.servers here to add new entry, use concat to put it as the first & default one
spec.servers = [{url: "#apiUrl"}]
spec.components.schemas["swagger"]["docs"]["are"]["very"]["dynamic"] = #Html(Json.toJson(giveItSomeArgs).toString);
return oriAction(spec)
}
}
}
}
}
}
],
layout: "StandaloneLayout",
onComplete: function() {
}
})
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>
There's your layout StandaloneLayout so I guess you have a handle there. You can add all the JavaScript in the world and knock yourself out. Check the Swagger docs on how to customize the layout.
Not sure about the whole React thing you suggest, that's another thing.

Obtaining a json return for html editor in FileMaker

I'm using the summernotes html form on a FileMaker solution to write emails. originally I had a save button to transfer the html uri into a field and then email that with the client scripts. However, users (and me...) don't like having to click "save" and then "send".
I'm wondering if anyone has any ideas on how to automate this. I tried to set the save function on a 1 second recurrence, however, that stops typing and removes the cursor. I'm thinking either someway to pull data via json or ideally some way I can interrogate it with my FileMaker 'send' script?
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML Editor</title>
<!-- include libraries(jQuery, bootstrap) -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- include summernote css/js -->
<script src="https://cdn.jsdelivr.net/npm/summernote#0.8.16/dist/summernote.min.js"></script>
<!-- <link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.11/summernote.css" rel="stylesheet"> -->
<link href="https://cdn.jsdelivr.net/npm/summernote#0.8.16/dist/summernote.min.css" rel="stylesheet">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script>
var intervalID;
function autoSave() {
intervalID = setInterval(saveText, 1000);
}
function saveText() {
//$('#summernote').summernote('code', 'code');
//window.alert('save changes');
/* Prep the URL to use for the hand-off to FM. */
var fullURL = '[[SAVEURL]]&param=' + encodeURIComponent ($('#summernote').summernote('code'));
/* Send the data to FM. */
window.location = fullURL;
return false;
}
</script>
</head>
<body onload ="autoSave();">
<div id="summernote">[[CONTENT]]</div>
<script>
}
$(document).ready(function() {
$('#summernote').summernote({
height: 300,
tabsize: 2,
toolbar: [
// [groupName, [list of button]]
['style', ['style','bold', 'italic', 'underline', 'clear']],
//['font', ['strikethrough', 'superscript', 'subscript']],
//['fontsize', ['fontsize']],
['color', ['color']],
//['para', ['ul', 'ol', 'paragraph']],
//['height', ['height']],
['insert', ['link']],
//['insert', ['link','hr','table']],
//['misc',['codeview']],
['mybutton',['save']]
],
buttons: {save: SaveButton}
});
});
</script>
</body>
</html>
Instead of passing the encoded HTML as a parameter in the URL (&param=...) - which causes the page to reload and thus causes the focus to be lost - try passing the parameter as an anchor (#...).
Like that the page won’t reload, and the focus should remain. Of course, you’ll have to adjust your parameter reading code accordingly.
Alternatively, if you have FileMaker 19 you can use the FileMaker.PerformScript or FileMaker.PerformScriptWithOption function to pass the value directly to a script.

How to disable letterboxing and adjust UI5 for the widescreen?

I have an UI5-based app (1.66+), which works correctly, but there are huge empty spaces on the left and right sides of the screen (aka letterboxing is on):
I want to disable letterboxing to use the entire screen space.
I tried the following approaches so far:
To use "fullWidth": true in sap.ui section of manifest.json
To add desktop-related classes to the HTML-tag in index.html:
<html class="sap-desktop sapUiMedia-Std-Desktop sapUiMedia-StdExt-LargeDesktop">
To add appWidthLimited: false to index.html:
<script>
sap.ui.getCore().attachInit(function () {
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
height: "100%",
name: "APPNAME"
}),
appWidthLimited: false
}).placeAt("content");
});
</script>
Just like it is described in «How to customise Shell container in SAPUI5».
But none of them works for me.
Update:
I succeeded to solve the issue via a static XML-template — just add <Shell id="shell" appWidthLimited="false"> to the main XML-template, but now I want to understand how to implement it via JS in new sap.m.Shell(…) definition.
The starting point for code experiments is below.
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>widescreen</title>
<script id="sap-ui-bootstrap"
src="../../resources/sap-ui-core.js"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-resourceroots='{"letterboxing.widescreen": "./"}'
data-sap-ui-compatVersion="edge"
data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
data-sap-ui-async="true"
data-sap-ui-frameOptions="trusted">
</script>
</head>
<body class="sapUiBody">
<div data-sap-ui-component data-name="letterboxing.widescreen" data-id="container" data-settings='{"id" : "widescreen"}' id="content"></div>
</body>
</html>
Component.js:
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/Device",
"letterboxing/widescreen/model/models"
], function (UIComponent, Device, models) {
"use strict";
return UIComponent.extend("letterboxing.widescreen.Component", {
metadata: {
manifest: "json"
},
init: function () {
// call the base component's init function
UIComponent.prototype.init.apply(this, arguments);
// enable routing
this.getRouter().initialize();
// set the device model
this.setModel(models.createDeviceModel(), "device");
}
});
});
Ok, so there seems to be many similar questions regarding how to disable/enable letterboxing. This answer should provide a solution for each case:
Standalone Apps
Look for the instantiation of sap.m.Shell in your project and configure appWidthLimited accordingly.
For example:
In index.html or index.js
sap.ui.require([
"sap/m/Shell",
"sap/ui/core/ComponentContainer",
], (Shell, ComponentContainer) => new Shell({
appWidthLimited: false|true, // <--
// ...
}).placeAt("content"));
In root view
<Shell xmlns="sap.m" appWidthLimited="false|true">
<App>
<!-- ... -->
Of course, the Shell can be configured dynamically in JS too with myShell.setAppWidthLimited.
Note: if the letterboxing is never required, please reconsider whether <Shell> in your app is necessary at all. There is no purpose of sap.m.Shell if the app is displayed always in full width.
API reference: sap.m.Shell
UX guideline: Letterboxing
Apps on SAP Fiori launchpad (FLP)
The component / app …:
should not contain sap.m.Shell anywhere (please check the root view).
launches from FLP instead (no index.html).
Statically in manifest.json
"sap.ui": {
"fullWidth": true|false,
...
},
Dynamically in runtime
// AppConfiguration required from "sap/ushell/services/AppConfiguration"
AppConfiguration.setApplicationFullWidth(true|false);
API reference: sap.ushell.services.AppConfiguration
UX guideline: Letterboxing
⚠️ Note: letterboxing is currently not supported by apps generated by SAP Fiori elements.
According to Available OpenUI5 Versions the newest OpenUI5 version is 1.65.0. How is you app based on 1.66.0?
Setting appWidthLimited: false on the sap.m.Shell should do the work. Check out this example (plunker / github) (in the Plunker run preview in a new window)
You can achieve that removing the shell control from index.html:
sap.ui.getCore().attachInit(function () {
sap.ui.require(["sap/ui/core/ComponentContainer"], function (ComponentContainer) {
new ComponentContainer({
name: "yourProject",
async: true,
manifest: true,
height: "100%"
}).placeAt("content");
});
});
instead of this:
<script>
sap.ui.getCore().attachInit(function () {
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
height: "100%",
name: "APPNAME"
}),
appWidthLimited: false
})
.placeAt("content");
});
</script>
Static implementation via XML-template:
<mvc:View controllerName="letterboxing.widescreen.controller.index" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m">
<Shell id="shell" appWidthLimited="false">
<App id="app">
<pages>
<Page id="page" title="{i18n>title}">
<content></content>
</Page>
</pages>
</App>
</Shell>
</mvc:View>
For dynamic implementation via JS-controller with appWidthLimited: false in sap.m.Shell, see: https://stackoverflow.com/a/55867413
For some reason, AppConfiguration.setApplicationFullWidth(true); does not work for me. I don't have a valid application container.
I solved the problem in this, admittedly hacky, way: In my app controller, I added this implementation of the onAfterRendering method:
onAfterRendering: function () {
var oElement = this.getView().byId("idAppControl").$();
while (oElement && oElement.hasClass) {
if (oElement.hasClass("sapUShellApplicationContainerLimitedWidth")) {
oElement.removeClass("sapUShellApplicationContainerLimitedWidth");
break;
}
oElement = oElement.parent();
}
}

Samsung TV SDK - getting a simple application working

I am attempting to get a very simple HTML/JavaScript application working for SDK 5.0b, the instructions for which are here...
http://samsungtvdev.blogspot.com/2013/04/smamsung-smart-tv-how-to-write-hello.html
I can launch VirtualBox 4.2.16 and see my application in the menu for the emulator. However, when I launch it, the background is black, and I don't see my application. I also see a bunch of warnings in the emulator about 'RegisterType()' and other functions not being available.
I tried posting this on the Samsung SDK forum, but it's pretty dead over there. I also tried the suggestion here, but copying the application manually also doesn't seem to work. Anyone have any ideas on how I can get this working?
Edit: Here is the HTML code. This isn't more than a "hello world" example.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>HelloWorld</title>
<!-- TODO : Common API -->
<script type="text/javascript" language="javascript" src="$MANAGER_WIDGET/Common/API/Widget.js"> </script>
<script type="text/javascript" language="javascript" src="$MANAGER_WIDGET/Common/API/TVKeyValue.js"> </script>
<!-- TODO : Javascript code -->
<script language="javascript" type="text/javascript" src="app/javascript/Main.js"></script>
<!-- TODO : Style sheets code -->
<link rel="stylesheet" href="app/stylesheets/Main.css" type="text/css">
<!-- TODO: Plugins -->
</head>
<body onload="Main.onLoad();" onunload="Main.onUnload();">
<!-- Dummy anchor as focus for key events -->
<!-- TODO: your code here -->
<div id="outputDiv"></div>
</body>
</html>
This is the JavaScript code.
var widgetAPI = new Common.API.Widget();
var tvKey = new Common.API.TVKeyValue();
var Main =
{
};
Main.onLoad = function()
{
// Enable key event processing
this.enableKeys();
widgetAPI.sendReadyEvent();
alert("App loaded!");
};
Main.onUnload = function()
{
};
Main.enableKeys = function()
{
document.getElementById("anchor").focus();
};
Main.keyDown = function()
{
var keyCode = event.keyCode;
alert("Key pressed: " + keyCode);
switch(keyCode)
{
case tvKey.KEY_RETURN:
case tvKey.KEY_PANEL_RETURN:
alert("RETURN");
widgetAPI.sendReturnEvent();
break;
case tvKey.KEY_LEFT:
alert("LEFT");
break;
case tvKey.KEY_RIGHT:
alert("RIGHT");
break;
case tvKey.KEY_UP:
alert("UP");
break;
case tvKey.KEY_DOWN:
alert("DOWN");
break;
case tvKey.KEY_ENTER:
case tvKey.KEY_PANEL_ENTER:
alert("ENTER");
document.getElementById("outputDiv").innerHTML += "<h1>Hello, World!</h1><br/>";
break;
default:
alert("Unhandled key");
break;
}
};
Here are the logs:
http://pastebin.com/mZULDGc6
1.) Look for misspellings, typos and missing commas. Samsung Smart TV SDK seems to be very strict with that and since you have no proper console, you don't get any errors if you forget a comma or something
2.) check your HTML/CSS
Maybe you should post your code so I can have a closer look.
EDIT: You forgot to add the scripts in your HTML head. You have to add every script file that you use in your project, such as Main.js. That would be
<script language="javascript" type="text/javascript" src="app/javascript/Main.js"></script>
and also all Samsung SmartTV API script files that are required.
First what i see, you forgot "anchor" tag in html.
Not included external JS files in html page, and standard smart tv sdk files:
<script type="text/javascript" language="javascript" src="$MANAGER_WIDGET/Common/API/Widget.js"> </script>
<script type="text/javascript" language="javascript" src="$MANAGER_WIDGET/Common/API/TVKeyValue.js"> </script>
Then add
<body onload="Main.onLoad();" onunload="Main.onUnload();">
Are you sure that images loaded? Print it in console.
Why div block position inside canvas, move it outside. I think that code started with js error, so you don't see anything. Be more careful.
I had same issue and fixed it by adding background: red; for body tag in css.

Incorrectly Linking Javascript File?

I'm working on installing a PhoneGap plugin on an iPhone. The page for the plugin I am attempting to install can be seen here: https://github.com/phonegap/phonegap-plugins/tree/master/iPhone/MessageBox.
I believe I have narrowed down my problem to incorrectly working with the JavaScript file. I am including it on my HTML page like so:
<script language="javascript" type="text/javascript" src="MessageBox.js"></script>
The rest of my HTML page is this:
<script type="text/javascript">
alert("test1");
var messageBox = window.plugins.messageBox;
alert("test2");
messageBox.alert('Title', 'Message', function(button) { console.warn('alert', [this, arguments]); });
</script>
I see an alert saying test1, but not the second alert. This makes me think that the error is on the line:
var messageBox = window.plugins.messageBox;
However, I'm not quite sure what I should be doing differently. From what I can tell, I've done all the necessary steps as described on the plugin's documentation page, seen here:
https://github.com/phonegap/phonegap-plugins/blob/master/iPhone/MessageBox/README.md
(As expected, I also do not see the output of the messageBox.alert... line when viewing this through the iOS simulator.)
I would appreciate any help with this issue, thanks!
NOTE: my initial thread regarding this topic can be seen here: Trouble Installing PhoneGap Plugin
EDIT: I should also add that I have the exact same problem when trying to install a different (but similar) plugin, known as "Prompt"
EDIT2: Here's my index.html:
<script type="text/javascript" charset="utf-8" src="phonegap-1.4.1.js"></script>
<script type="text/javascript" src="MessageBox.js"></script>
<script type="text/javascript">
function onBodyLoad()
{
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady()
{
navigator.notification.alert("PhoneGap is working");
window.location.href="otherpage.html";
}
</script>
The problem is that when you try to create your MessageBox, PhoneGap is not ready yet.
You just need to wait for PhoneGap to be ready before you execute your code :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script type="text/javascript" charset="utf-8" src="phonegap-1.4.1.js"></script>
<script type="text/javascript" charset="utf-8">
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
window.location="otherpage.html";
}
</script>
</head>
<body>
</body>
</html>
Then, on otherpage.html :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script type="text/javascript" charset="utf-8" src="phonegap-1.4.1.js"></script>
<script type="text/javascript" charset="utf-8" src="MessageBox.js"></script>
</head>
<body onload="onLoad()">
<script type="text/javascript" charset="utf-8">
function onLoad() {
document.addEventListener("deviceready", onDeviceReady, false);
}
// PhoneGap is loaded and it is now safe to make calls PhoneGap methods
//
function onDeviceReady() {
console.log("onLoad");
var messageBox = window.plugins.messageBox;
messageBox.alert('Title', 'Message', function(button) { console.warn('alert', [this, arguments]); });
}
</script>
</body>
</html>
I tested it on PhoneGap 1.4.1