UIKit 3 accordion external button - uikit

How to close\ open accorion on click to .shewron element?
Example: https://codepen.io/npofopr/pen/vYKKXbJ?editors=1010
let util = UIkit.util;
let lkOrderIconExpand = document.querySelectorAll(".shewron");
util.on(lkOrderIconExpand, "click", function () {
let accordionEl = util.$("[uk-accordion]");
// find closed li array
let allItems = util.$$("[uk-accordion] > li");
// for each element
util.each(allItems, function (el) {
// get index
let openIndex = util.index(el);
// Check if some element has some class
if (util.hasClass(allItems, "uk-open")) {
console.log("Class was found!");
// toggle it
UIkit.accordion(accordionEl).toggle(openIndex);
} else {
console.log("Class was NOT found!");
// toggle it
UIkit.accordion(accordionEl).toggle(openIndex);
}
});
});

You can easily do it with CSS:
.uk-accordion-title::before{
background-image: url(**icon-url-here);
}
.uk-open > .uk-accordion-title::before{
background-image: url(**icon-url-here);
}
So that your chevron icons will show instead of default accordion icons.

Related

How to Show 30 days in Day View with Horizontal Scrollbar in Dhtmlx Scheduler?

I want to show 30 days in Day View Scheduler with Horizontal Scrollbar. Currently, Horizontal Scrollbar is available only for Timeline View but I want it for Day View as well as Month View.
For Timeline View with Horizontal Scrollbar code:
scheduler.createTimelineView({
name: "timeline",
x_unit: "minute",
x_date: "%H:%i",
x_step: 30,
x_size: 24*7,
x_start: 16,
x_length: 48,
y_unit: sections,
y_property: "section_id",
render: "bar",
scrollable: true,
column_width: 70,
scroll_position:new Date(2018, 0, 15) });
Please share your ideas and Sample links
Thanks in Advance
Try using Custom View. You can remove the default Day view and display your own instead, with the number of days you want to display. This can be done like this:
First in scheduler.config.header set tab "thirty_days" instead of "day":
scheduler.config.header = [
"thirty_days",
"week",
"month",
"date",
"prev",
"today",
"next"
];
The label for the view is set as in:
scheduler.locale.labels.thirty_days_tab = "Days";
Next, set the start date of the viewing interval, as well as viewing templates. It's better to create the custom view in the onTemplatesReady event handler function so that your custom view templates are ready before the scheduler is initialized:
scheduler.attachEvent("onTemplatesReady", () => {
scheduler.date.thirty_days_start = function(date) {
const ndate = new Date(date.valueOf());
ndate.setDate(Math.floor(date.getDate()/10)*10+1);
return this.date_part(ndate);
}
scheduler.date.add_thirty_days = function(date,inc) {
return scheduler.date.add(date,inc*30,"day");
}
const format = scheduler.date.date_to_str(scheduler.config.month_day);
scheduler.templates.thirty_days_date = scheduler.templates.week_date;
scheduler.templates.thirty_days_scale_date = function(date) {
return format(date);
};
});
To add horizontal scrolling to the view, you can place the scheduler inside the scrollable element and give the scheduler the width required to display all columns. You'll need to hide a default navigation panel of the scheduler and create a custom one with HTML, so it would have a correct width and won't be affected by scrolling:
scheduler.xy.nav_height = 0;
scheduler.attachEvent("onSchedulerReady", function () {
const navBar = scheduler.$container.querySelector(".dhx_cal_navline").cloneNode(true);
navBar.style.width = "100%";
document.querySelector(".custom-scheduler-header").appendChild(navBar);
document.querySelectorAll(".custom-scheduler-header .dhx_cal_tab").forEach(function (tab) {
tab.onclick = function () {
const name = tab.getAttribute("name");
const view = name.substr(0, name.length - 4);
scheduler.setCurrentView(null, view);
};
});
document.querySelector(".custom-scheduler-header .dhx_cal_prev_button").onclick = function () {
const state = scheduler.getState();
scheduler.setCurrentView(scheduler.date.add(state.date, -1, state.mode));
};
document.querySelector(".custom-scheduler-header .dhx_cal_next_button").onclick = function () {
const state = scheduler.getState();
scheduler.setCurrentView(scheduler.date.add(state.date, 1, state.mode));
};
document.querySelector(".custom-scheduler-header .dhx_cal_today_button").onclick = function () {
scheduler.setCurrentView(new Date());
};
scheduler.attachEvent("onBeforeViewChange", (oldView, oldDate, newView, newDate) => {
const innerContainer = document.getElementById("scheduler_here");
if (newView === "thirty_days") {
innerContainer.style.width = "3000px";
} else {
innerContainer.style.width = "100%";
}
return true;
});
scheduler.attachEvent("onViewChange", function (view, date) {
const dateLabel = document.querySelector(".custom-scheduler-header .dhx_cal_date");
const state = scheduler.getState();
dateLabel.innerHTML = scheduler.templates[view + "_date"](state.min_date, state.max_date);
document.querySelectorAll(".custom-scheduler-header .dhx_cal_tab").forEach(function(tab) {
tab.classList.remove("active");
});
const activeTab = document.querySelector(".custom-scheduler-header ." + view + "_tab");
if (activeTab) {
activeTab.classList.add("active");
}
});
});
Styles that you will need:
.custom-scheduler-header .dhx_cal_navline{
display: block !important;
height: 60px !important;
}
.custom-scheduler-header .dhx_cal_navline.dhx_cal_navline_flex{
display: flex !important;
}
.dhx-scheduler {
height: 100vh;
width: 100vw;
position: relative;
overflow: hidden;
background-color: #fff;
font-family: Roboto, Arial;
font-size: 14px;
}
.dhx_cal_container .dhx_cal_navline {
display: none;
}
Please see an example: https://snippet.dhtmlx.com/znd7ffiv
You may need to fix the hour scale so that it remains visible when scrolling horizontally on the calendar. I did not implement this in the example, I think that this can be done in the same way as for the navigation panel. If you need, write to me and I will send an update in a few working days.
As for the "Month" view, the approach is the same as for the "Day" view.

How do I make my own window frame in egui (eframe) Rust

Here is how I start my app and remove the window frame:
let app = RustClicker::default();
let mut native_options = eframe::NativeOptions::default();
native_options.decorated = false; // I remove window frame here
eframe::run_native(Box::new(app), native_options);
I made my own top-panel like this:
egui::TopBottomPanel::top("decoration").show(ctx, |ui| {
egui::menu::bar(ui, |ui| {
ui.with_layout(egui::Layout::left_to_right(), |ui| {
ui.label("🖱");
});
ui.with_layout(egui::Layout::right_to_left(), |ui| {
if ui.button("🗙").clicked() {
frame.quit();
}
let change_theme = ui.button("🎨");
if change_theme.clicked() {
if self.dark_theme {
self.dark_theme = false;
}
else {
self.dark_theme = true;
}
}
});
});
});
But I can't move it with holding moue button on, TopPanel is there anyway to fix this?
Found an example https://github.com/emilk/egui/tree/master/examples/custom_window_frame this works and the corners are also rounded

Incorrect behavior of content editable div in custom element shadowRoots in Firefox?

I have a program that includes some nested custom elements. The leaves of one of these component's shadowRoot contains instances of an element like <div contentEditable>. In Chrome79 and Chromium-Edge-Beta the contentEditable feature works as one would expect it to - that is, the elements focus when you click or tab to them, show a focus outline, and are editable. In FireFox72 they behave erratically, mainly in that clicking on one will focus on it only some of the time, and that while they can be tabbed to, they do not focus such that they can be typed into.
After some whittling, I think I've arrived at a minimal reproduction. It is two custom elements: A root element ce-main and the leaf element ce-leaf that is instantiated arbitrarily many times from within ce-main and attached to ce-main's shadowRoot.
class Main extends HTMLElement {
constructor() { super(); }
connectedCallback() {
this.attachShadow({mode: "open"});
this.shadowRoot.innerHTML = `
<style>
[contentEditable] {
min-height:2em;
padding:.5em;
border:1px dashed rgba(0,0,0,.0625);
}
[contentEditable]:empty::before {
color: rgba(0,0,0,.15);
content: "You should be able to focus and type here.";
cursor:text;
}
</style>
<div id="container" style=""></div>`;
customElements.whenDefined("ce-leaf").then(
() => this.constructFromSomeDataSource()
);
}
constructFromSomeDataSource() {
let rows = [];
for (let i = 0; i < 4; i++) {
let leaf = document.createElement("ce-leaf");
this.shadowRoot.querySelector("#container").appendChild(leaf);
};
}
}
class Leaf extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = `
<div contentEditable></div>
`;
}
}
customElements.define("ce-main", Main);
customElements.define("ce-leaf", Leaf);
<ce-main></ce-main>
If we do without the shadowRoot, everything is nicely focusable in Chrome/EdgeBeta/Firefox:
class Main extends HTMLElement {
constructor() { super(); }
connectedCallback() {
customElements.whenDefined("ce-leaf").then(
() => this.constructFromSomeDataSource()
);
}
constructFromSomeDataSource() {
let rows = [];
for (let i = 0; i < 4; i++) {
let leaf = document.createElement("ce-leaf");
this.appendChild(leaf);
};
}
}
class Leaf extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = `
<div contentEditable></div>
`;
}
}
customElements.define("ce-main", Main);
customElements.define("ce-leaf", Leaf);
[contentEditable] {
min-height:2em;
padding:.5em;
border:1px dashed rgba(0,0,0,.0625);
}
[contentEditable]:empty::before {
color: rgba(0,0,0,.15);
content: "You should be able to focus and type here.";
cursor:text;
}
<ce-main></ce-main>
Can anyone verify if this is a bug in FF, or if I am simply doing something that is not in line with how it should be done in FF?
Had to dig through many Firefox/Focus posts.
Similar behaviour in a FireFox bug going back some 6 years: https://bugzilla.mozilla.org/show_bug.cgi?id=904846
Workaround
Found the best approach here: Clicking outside a contenteditable div stills give focus to it?
Handle the contenteditable attribute and setting focus() yourself with click & blur events:
(note: leafCounter is valid CSS, just does not work in StackOverflow inline code, works in JSFiddle)
class Main extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.attachShadow({ mode: "open" })
.innerHTML = `<style>
ce-leaf div {
padding: .5em;
cursor: text;
counter-increment: leafCounter;
}
ce-leaf div:empty::before {
color: lightgrey;
content: "placeholder text #" counter(leafCounter);
}
[contenteditable]:focus{
background: lightgreen;
}
</style>` + "<ce-leaf></ce-leaf>".repeat(5);
}
}
class Leaf extends HTMLElement {
constructor() {
super();
let div = this.appendChild(document.createElement("div"));
div.addEventListener("click", evt => {
evt.target.contentEditable = true;
evt.target.focus();
});
div.addEventListener("blur", evt => {
evt.target.contentEditable = false;
});
}
}
customElements.define("ce-main", Main);
customElements.define("ce-leaf", Leaf);
<ce-main></ce-main>
<ce-leaf> IS an element!
You don't need that DIV inside a <ce-leaf> Custom Element...
JSFiddle version does the contenteditable on <ce-leaf>
https://jsfiddle.net/dannye/udmgL03p/
constructor() {
super();
this.addEventListener("click", evt => {
this.contentEditable = true;
this.focus();
});
this.addEventListener("blur", evt => {
this.contentEditable = false;
});
}
Update: Alas another Firefox with contenteditable bug: You can't select part of a text and replace it in the JSfiddle..
stick with the DIV inside an element solution.

How to make a context menu in a custom ckeditor5 widget?

I made a inline widget similar a placeholder (ckeditor4), but now I want to render a dropdown when the widget is selected to show options values to replace the placeholder. I trying use BalloonPanelView but no success until now, someone have a idea about how to make it?
this.editor.editing.view.document.on('click', (evt, data) => {
evt.stop();
const element = data.target;
if (element && element.hasClass('placeholder')) {
if (!element.getAttribute('data-is-fixed')) {
const balloonPanelView = new BalloonPanelView();
balloonPanelView.render();
['option1', 'option2', 'option3'].forEach((value) => {
const view = new View();
view.set({
label: value,
withText: true
});
balloonPanelView.content.add(view);
});
balloonPanelView.pin({
target: element
});
}
}
});
I found the solution using ContextualBalloon class:
import ContextualBalloon from "#ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon";
// Define ballon
const balloon = editor.plugins.get(ContextualBalloon);
const placeholderOptions = // Here I defined list with buttons '<li><button></li>'
// Finnaly render ballon
balloon.add({
view: placeholderOptions,
singleViewMode: true,
position: {
target: data.domTarget
}
});

Ckeditor plugin : how to unwrap text?

I have created a ckeditor plugin that wraps the selected text into a span.
I wonder how can I unwrap the selected when I apply this plugin on a text that has been previously wrapped into the span.
CKEDITOR.plugins.add('important', {
// Register the icons. They must match command names.
//trick to get a 16*16 icon : http://www.favicomatic.com
icons: 'important',
init: function (editor) {
editor.addCommand('important', {
// Define the function that will be fired when the command is executed.
exec: function (editor) {
var selected_text = editor.getSelection().getSelectedText();
console.log(editor.getSelection()) ;
var newElement = new CKEDITOR.dom.element("span");
newElement.setAttributes({class: 'important'});
newElement.setText(selected_text);
editor.insertElement(newElement);
//how to unwrap the selected text ?
});
// Create the toolbar button that executes the above command.
editor.ui.addButton('important', {
label: 'Set this as important',
command: 'important',
toolbar: 'insert'
});
}
});
Finally, using editor.getSelection().getStartElement(), I can check if the starting element has already been wrapped with the class and remove it if necessary.
CKEDITOR.plugins.add('important', {
//trick to get a 16*16 icon : http://www.favicomatic.com
icons: 'important',
init: function (editor) {
var className = 'important';
editor.addCommand('important', {
// Define the function that will be fired when the command is executed.
exec: function (editor) {
var editorSelection = editor.getSelection();
var selected_text = editorSelection.getSelectedText();
var startElement = editorSelection.getStartElement();
//if the element has already been wrapped, let's UNwrap it
if (className === startElement.$.className) {
var html = startElement.$.innerHTML;
editor.getSelection().getStartElement().remove();
editor.insertHtml(html);
} else {
//if the element has NOT already been wrapped, let's wrap it
var newElement = new CKEDITOR.dom.element("span");
newElement.setAttributes({class: 'important'});
newElement.setText(selected_text);
editor.insertElement(newElement);
}
}
});
// Create the toolbar button that executes the above command.
editor.ui.addButton('important', {
label: 'Set this as important',
command: 'important',
toolbar: 'insert'
});
}
});

Resources