Hi I have an app that is basically a html page.
I have a problem though as the html page is longer than the viewable screen and the page wont scroll.
Ive added this div:
<div id="scrollerId" style="width:320px; height:100px" x-mojo-element="Scroller">
<div >scrolling content</div>
</div>
but it doesn't do anything.
Please can someone help explain how to add one. or if i need to add anything to my javascript file or anything else ?
source/helloworld.js
enyo.kind({
name: "HelloWorld",
kind: enyo.VFlexBox,
components: [
{kind: "PageHeader", components: [
{content: "Page Header"}
]},
{flex: 1, kind: "Pane", components: [
{flex: 1, kind: "Scroller", components: [
//Insert your components here
]}
]},
{kind: "Toolbar", components: [
]}
]
});
Im a newbie to webos dev so go easy on me.
It might help to know what device(s) you're targeting. You've got a mix of a Mojo app and an Enyo app there, it looks like. Mojo is for the phones. If you're targeting the TouchPad, you should probably switch entirely to Enyo.
For the Mojo scroller to work in webOS you need to enable it as follows:
this.controller.setupWidget("myScroller",
this.attributes = {
},
this.model = {
scrollbars: true,
mode: "free"
});
You can read more about scrollers in Mojo here:
http://webos101.com/Scroller
However, I think you want an Enyo scroller so you get rid of the HTML in your app and use the method described above by XRay Enabler.
It is possible to use JavaScript functions to pull in content from a DIV in your HTML into an Enyo kind. Here's an example using jQuery:
this.$.myContent.setContent($("#someDiv").html());
Keep in mind you'll have to set allowHtml to true to allow HTML content.
First of all welcome to Enyo and webOS! Try to remember that Enyo is your framework that will create the elements of your HTML (the app). You generally do not manipulate it (HTML) directly.
As a simple example, you can create your content after the kind 'HelloWorld' has been rendered:
** your previous code **
{flex: 1, kind: "Scroller", components: [
//Insert your components here
{content: "", name:"myContent"}
]}
]},
{kind: "Toolbar", components: []}
],
create: function() {
this.inherited(arguments);
},
rendered: function() {
this.$.myContent.setContent("I can now add Content!");
}
});
Notice the added content container called myContent in the Scoller. Also, remove the previously created div's in your HTML file.
The content is then added in the rendered function.
Related
I create custom ckeditor 5 build in https://ckeditor.com/ckeditor-5/online-builder/ (based on "decoupled component" type), at the end i download zip with files. But what I am supposed to do next how to import it in main.js / package.js and finnaly to component ?
All materials I was able to find are https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/vuejs-v3.html , got decoupled-document preset build working, but wanted to add image resize, so created custom build and am stuck at that point.
Tnx for any response.
This post is maybe longer but its super easy 5min done.
[2022 updated, still works, just config moved in another file, also people may return there because of higher Vue version ckeditor5 toolbar disappear and update/reinstall is needed]
This example is for full document type of ckeditor 5, decoupled-document is almost everything You need, just it lacks image-resize, to add it go to https://ckeditor.com/ckeditor-5/online-builder/ click it all way and add image-resize or all other fun stuff (You do not need premium Ckfinder, but You probably need CKFinder upload adapter for images uplad which is free), and download zip file, do not forget to pick same type in step 1 as one you will use/install.
Install (like in classic guide - https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/vuejs-v3.html)
npm install --save #ckeditor/ckeditor5-vue #ckeditor/ckeditor5-build-decoupled-document
(if here because of re-install, just remove package.json #ckeditor lines and run above install command again)
In main.js
import CKEditor from '#ckeditor/ckeditor5-vue';
createApp(App)
.use(router)
.use(CKEditor)
.mount("#app");
In your component
import DocumentEditor from '#ckeditor/ckeditor5-build-decoupled-document';
Now add config to data, You can find this config generated inside files you got from online-builder generator its copy/paste so do not freak out :) . You can find it in /src/ckeditor.js in defaultConfig, if you do not set it its possible You'll see an warning about missing "toolbar" options. Do not copy what you see below, use your custom generated config, its only for illustration :
data: function () {
return{
editorConfig: {
ckfinder: {
uploadUrl: 'https://page.com/api/uploadckeditor'
},
toolbar: {
items: [
'heading',
'|',
'bold',
'italic',
'link',
'bulletedList',
'numberedList',
'|',
'outdent',
'indent',
'|',
'imageUpload',
'blockQuote',
'insertTable',
'mediaEmbed',
'undo',
'redo',
'alignment',
'codeBlock',
'fontBackgroundColor',
'fontColor',
'fontFamily',
'fontSize',
'highlight',
'horizontalLine',
'htmlEmbed',
'imageInsert',
'pageBreak',
'removeFormat',
'strikethrough',
'underline',
'style'
]
},
language: 'cs',
image: {
toolbar: [
'imageTextAlternative',
'imageStyle:inline',
'imageStyle:block',
'imageStyle:side',
'imageStyle:alignLeft',
'imageStyle:alignRight',
'imageStyle:alignCenter',
'imageStyle:alignBlockLeft',
'imageStyle:alignBlockRight',
'linkImage'
]
},
table: {
contentToolbar: [
'tableColumn',
'tableRow',
'mergeTableCells',
'tableCellProperties',
'tableProperties'
]
},
fontFamily: {
options: [
'default',
'indieflowerregular',
'Arial, sans-serif',
'Verdana, sans-serif',
'Trebuchet MS',
'Apple Color Emoji',
'Segoe UI Emoji',
'Segoe UI Symbol',
]
},
licenseKey: ''
}
};
}
Now use it in component html
<ckeditor :editor="editor" #ready="onReady" v-model="editorData" :config="editorConfig"></ckeditor>
Decoupled component ckeditor package need #ready="onReady" othervise it will not initialize (classic do not need this)
here is method :
methods: {
onReady( editor ) {
// Insert the toolbar before the editable area.
editor.ui.getEditableElement().parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
},
Ok now You have almost everything done just last magic thing to do .
In files you downloaded go to /build folder and COPY all the files into
"node_modules#ckeditor\ckeditor5-build-decoupled-document\build" and override initial decoupled-document. This is key thing to do, even thought it sounds pretty horrible.
Bonus : I wanted to have also image upload so added to config
**ckfinder: {
uploadUrl: 'http://mypage/api/uploadckeditor'
},**
Here is php side implementation its just basic one wit no error handling
$uploaddir = '../www/adminUpload/';
$uploadfile = $uploaddir . basename($_FILES['upload']['name']);
if (move_uploaded_file($_FILES['upload']['tmp_name'], $uploadfile)) {
//$this->sendJson(array("message"=>"sucess"));
} else {
//$this->sendJson(array("message"=>"failed"));
}
$returnArray = array();
$returnArray["uploaded"] = true;
$returnArray["url"] = "http://www.mypage.com/adminUpload/".$_FILES['upload']['name'];
header('Content-type: application/json');
$this->sendJson($returnArray);
$this->terminate();
For last 2 rows they are Nette php framework specific, just send out $returnArray as json response.
Here is how I integrated CKEDITOR with Vue3.js
Install required packages
npm install --save #ckeditor/ckeditor5-vue #ckeditor/ckeditor5-build-classic
main.ts
import CKEditor from '#ckeditor/ckeditor5-vue'
const app = createApp(App)
app.use( CKEditor ).mount('#app')
Then in your component where you wnat to use ckeditor
<template>
<ckeditor :editor="editor" v-model="data.description"></ckeditor>
</template>
<script>
import {onMounted, reactive, computed} from "vue"
import ClassicEditor from '#ckeditor/ckeditor5-build-classic'
export default{
name:'Add',
setup() {
//....
const data = reactive({
description: '',
})
return {
data,
editor: ClassicEditor
}
}
}
</script>
enter code here
I faced a problem image uploading inside ckeditor5-build-classic,
for image uploading I'm using Node.js server and S3, here is how returned the json response from Node.js server, uploaded flag is more important:
exports.upload_file_ckeditor = async(req, res) => {
let obj = {
"uploaded" : true,
"url" : 'http://example.com/upload/xyz.png'
}
return res.send(obj)
}
I created a new Symfony4 project and installed EasyAdmin bundle (which works fine).
I tried to integrate CKeditor following the documentation : https://symfony.com/doc/master/bundles/EasyAdminBundle/integration/ivoryckeditorbundle.html
Here is my easyadmin.yaml:
easy_admin:
entities:
TestPage:
class: App\Entity\TestPage
form:
fields:
- { property: 'content', type: 'fos_ckeditor', type_options: { 'config': { 'toolbar': [ { name: 'styles', items: ['Bold', 'Italic', 'BulletedList', 'Link'] } ] } }}
here my fos_ckeditor.yaml :
twig:
form_themes:
- '#FOSCKEditor/Form/ckeditor_widget.html.twig'
fos_ck_editor:
input_sync: true
default_config: base_config
configs:
base_config:
toolbar:
- { name: "styles", items: ['Bold', 'Italic', 'BulletedList', 'Link'] }
The problem is it's still the regular textarea that is showing, not the ckeditor rich text one.
I tried to clear the cache, to add "- '#FOSCKEditor/Form/ckeditor_widget.html.twig'" in twig.yaml but i still can't see the ckeditor toolbar.
Anyone has an idea on what i'm missing ?
Thanks!
vkhramtsov on git has just advised me to add the "#FOSCKEditor/Form/ckeditor_widget.html.twig" form theme to "easyadmin:design: form_theme:list" in "config/packages/easy_admin.yaml" like this:
easy_admin:
design:
form_theme: # Both themes are needed for ckeditor integration
- "#EasyAdmin/form/bootstrap_4.html.twig"
- "#FOSCKEditor/Form/ckeditor_widget.html.twig"
This solved the problem for me. I think the docs need to be updated. The place they suggest to put the form template presently (twig:form_themes) does not work.
How is sorting and filtering implemented when using a custom header cell in the react-data-grid?
{
key: "myColumn1",
name: "My Column Name",
headerRenderer: this.renderHeader,
sortable: true,
filterable: true
},
{
key: "myColumn2",
name: "My Other Column Name",
sortable: true,
filterable: true
}
...
renderHeader(props){
return (<extra-stuff>
{props.column.name}
</extra-stuff>)
}
I have myColumn2 sorting fine but nothing happens with the custom header: myColumn1. What do I need to do in renderHeader(){} to get sorting (and filtering, but mainly sorting) working?
Instead of trying to call a function in headerRenderer, put a component instead:
{
key: "myColumn1",
name: "My Column Name",
headerRenderer: <renderHeader value={this.renderHeader()} />,
sortable: true,
filterable: true
},
Looks like a solution was checked-in for this almost a year ago. I do work on an intranet and don't have direct internet access for development so maybe i have an older version. Since I can't get the version in my environment I'll wait for someone to verify that the latest version works as expected before I accept my own answer (or I'll try to get the latest version with the change in there.)
One other thing I will have to do with the way the solution was implemented is stop propagation of the click event because in my custom header i have a ReactIcon that is clickable to change from status wording to a menu. So, if they click right on the icon in the header do the name/menu change and if they click anywhere else in the header then do the sort. I'll have to look up how to do that in React.
Update
I took the changes from the check-in in the link above and added them to my react-data-grid.js and it works great. I.e. I had to add the changes to the pure javascript version of the code that npm pulled into our node_modules.
I also did have to use e.stopPropagation() call in my headerRenderer like i thought i'd have to so that clicking the icon i have in the headerRenderer would not sort when click (but just do a different operation) but it was easy to add.
I do have one question about the change i made to my js which here is a piece of the change...
return React.createElement(
'div',
{className: className,
onClick: this.onClick,
style: {cursor: 'pointer'} },
React.createElement(
'span',
{ className: 'pull-right' },
this.getSortByText()
),
//change was here from just: this.props.column.name
this.props.column.headerRenderer? this.props.column.headerRenderer(this.props) : this.props.column.name
);
How would i have done this in JavaScript so that it would work whether my headerRenderer was ()=>{ return <span>...</span> } or <MyComponent /> ???
Since i always use functions for my headerRenderer i just did the change so that it worked the one way but would like to know how to make the change so it works both ways. Something like this? ...
this.props.column.headerRenderer?
(isFunction(this.props.column.headerRenderer)? this.props.column.headerRenderer(this.props) : React.createElement(this.props.column.headerRenderer, {...this.props}) )
:
this.props.column.name
????
This is using the standard ExtJS 4 MVC library and structure.
I am trying to attach multiple views to a single controller so I can create instances of them later to add to panels. Unfortunately I am getting errors about the view when I add the second one and ExtJS is blocking the syntax errors it appears so that I am unable to see where the issue is.
If I comment out ViewOrders from the list below it works fine, but if it is in there then I get the following error:
An uncaught error was raised with the following data: ext-all-debug-with-comments.js (line 7864)
msg:
"The following classes are not declared even if their files have been loaded: 'PVAL_App.view.ViewOrders'. Please check the source code of their corresponding files for possible typos: 'app/view/ViewOrders.js'"
sourceClass: "Ext.Loader"
sourceMethod: "onFileLoaded"
Here is my controller:
Ext.define('PVAL_App.controller.Viewport', {
extend: 'Ext.app.Controller',
views: [
'Viewport', 'ViewOrders'
],
init: function() {
console.log('Viewport controller init()');
}
});
Here is my ViewOrders view:
Ext.define('PVAL_APP.view.ViewOrder', {
/* Begin Definitions */
extend: 'Ext.panel.Panel',
alias: 'widget.ViewOrders',
requires: [
'Ext.panel.Panel',
'Ext.data.ArrayStore'
],
border:false,
layout: 'fit',
//autoScroll: true,
initComponent: function() {
}
});
I doubt this is needed but this is my application file:
Ext.Loader.setConfig(
{
enabled: true
});
Ext.application({
name: 'PVAL_App',
appFolder: 'app',
autoCreateViewport: true,
controllers: [
'PVAL_App', 'Viewport'
],
launch:function() {
// Nothing yet.
//console.log(this.controllers);
}
});
I cannot seem to figure out if it is a syntax error or if this is an issue with the framework. I have experienced close to the same issue if I try to link to another controller from within one which makes me believe that this might be a constraint of the framework.
The problem here is that the class name in your app/view/ViewOrders.js script does not match the view name. Instead of Ext.define('PVAL_APP.view.ViewOrder', { you need the plural (and correct case) Ext.define('PVAL_App.view.ViewOrders', {. Either that our you can change your filename and refernece to the singular and just correct the case.
My question, while at first somewhat similar to this one, seems to be a more basic question - and might be signaling a bug in the build system. I've created a custom build for my dojo application. I only build one layer right now, here's what the profile script/object looks like:
dependencies = {
stripConsole: "all",
action: "release",
optimize: "shrinksafe",
releaseName: "myProject",
// list of locales we want to expose
localeList: "en-gb,en-us,de-de",
layers: [
{
// Name: a relative path from the dojo.js in the desination directory.
name: "../../myProject.js",
dependencies: [
"myPackage.MyDataStore",
// MyWidget depends on a few other widgets, and has its own
// translation files.
"myPackage.MyWidget"
]
}
],
prefixes: [
// These paths are relative to the location of dojo.js
[ "dijit", "../dijit" ],
[ "dojox", "../dojox" ],
[ "myPackage", "../../../src/myPackage" ]
]
}
When I run a build with that description it outputs files in the following directory structure:
release/
release/myProject/
release/myProject/dijit/
... dijit ...
release/myProject/dojo/
... dojo ...
release/myProject/dojox/
... dojox ...
release/myProject/myPackage/
... my custom package ...
release/nls/
myProject_en-us.js
myProject_de.js
etc..
../myproject.js
../myProject.js.uncompressed.js
Finally, in my test HTML page - I've got the following:
<script type="text/javascript">
var djConfig = {
debug: true,
parseOnLoad: false,
modulePaths: { // paths to directories in relation to dojo's location.... hurr.
'myPackage': '../myPackage',
'dojox': '../dojox',
'dijit': '../dijit'
}
};
</script>
<script type="text/javascript" src="./release/myProject/dojo/dojo.js.uncompressed.js"></script>
<script type="text/javascript" src="./release/myProject.js.uncompressed.js"></script>
<script type="text/javascript">
dojo.addOnLoad(function(){
dojo.require('myPackage.MyDataStore');
dojo.require('myPackage.MyWidget');
var store = new myPackage.MyDataStore();
var widget = new myPackage.MyWidget({
store: store
}, dojo.byId('testWidget'));
widget.startup();
});
</script>
But unfortunately, Firebug spits this out at me:
Bundle not found: MyWidget in myPackage , locale=en-us
What I Think is Happening
I've traced through some of the code leading up to the above error and it seems like the dojo.i18n._preloadLocalizations() call at the end of the file doesn't actually load in the correct nls file from ./release/nls.
Any idea how to fix this without resorting to manually including the nls files with <script> tags?
It's a bug of dojo, you should not use '..' in your layers name in case it will generate a NLS package.
please refer to http://bugs.dojotoolkit.org/ticket/5225