font-awesome icon in display of combobox extjs 6 - css

I tried several ways to set an icon, in the displayfield, when an item of the combo is selected with not luck, this is the fiddle for anyone to want try to help with this. very much appreciated any light.
fiddle example

The only solution is to transform the input type combo in a div with this:
fieldSubTpl: [
'<div class="{hiddenDataCls}" role="presentation"></div>',
'<div id="{id}" type="{type}" style="background-color:white; font-size:1.1em; line-height: 2.1em;" ',
'<tpl if="size">size="{size}" </tpl>',
'<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
'class="{fieldCls} {typeCls}" autocomplete="off"></div>',
'<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
'{triggerEl}',
'<div class="{clearCls}" role="presentation"></div>',
'</div>', {
compiled: true,
disableFormats: true
}
],
Override the setRawValue method of the combo like this:
setRawValue: function (value) {
var me = this;
me.rawValue = value;
// Some Field subclasses may not render an inputEl
if (me.inputEl) {
// me.inputEl.dom.value = value;
// use innerHTML
me.inputEl.dom.innerHTML = value;
}
return value;
},
and style your fake combo div like you want.
Thats because an input on HTML can't have HTML like value inside it.
Keep attenction, the get Value method will return you the HTML inside the div, and maybe you should also override it, but thats the only one method.
You will be able to get the selected value with this method:
Ext.fly(combo.getId()+'-inputEl').dom.innerHTML.replace(/<(.|\n)*?>/gm, '');
If I were you I would like to do something like this:
combo.getMyValue();
So add this property to your combo:
getMyValue:function(){
var combo=this;
if(Ext.fly(combo.id+'-inputEl'))
return Ext.fly(combo.id+'-inputEl').dom.innerHTML.replace(/<(.|\n)*?>/gm, '');
},
Here is a working fiddle

Perhaps my solution is similar to a hack, but it works in 6.7.0 and is a bit simpler.
Tested in Chrome. Theme - Material. For another theme will require minor improvements.
Sencha Fiddle live example
Ext.application({
name: 'Fiddle',
launch: function () {
var store = new Ext.data.Store({
fields: [{
name: 'class',
convert: function (value, model) {
if (value && model) {
var name = value
.replace(/(-o-)|(-o$)/g, '-outlined-')
.replace(/-/g, ' ')
.slice(3)
.trim();
model.data.name = name.charAt(0).toUpperCase() + name.slice(1);
return value;
}
}
}, {
name: 'name'
}],
data: [{
class: 'fa-address-book'
}, {
class: 'fa-address-book-o'
}, {
class: 'fa-address-card'
}]
});
var form = Ext.create('Ext.form.Panel', {
fullscreen: true,
referenceHolder: true,
items: [{
xtype: 'combobox',
id: 'iconcombo',
queryMode: 'local',
editable: false,
width: 300,
valueField: 'class',
displayField: 'name',
store: store,
itemTpl: '<div><i class="fa {class}"></i> {name}</div>',
afterRender: () => {
var component = Ext.getCmp('iconcombo');
var element = document.createElement('div');
element.className = 'x-input-el';
element.addEventListener('click', () => component.expand());
component.inputElement.parent().dom.prepend(element);
component.inputElement.hide();
component.addListener(
'change', (me, newValue, oldValue) => {
component.updateInputValue.call(me, newValue, oldValue);
},
component
);
var method = component.updateInputValue;
component.updateInputValue = (value, oldValue) => {
method.call(component, value, oldValue);
var selection = component.getSelection();
if (selection) {
element.innerHTML =
'<div><i class="fa ' + selection.get('class') + '"></i> ' + selection.get('name') + '</div>';
}
};
}
}, {
xtype: 'button',
text: 'getValue',
margin: '30 0 0 0',
handler: function (component) {
var combo = Ext.getCmp('iconcombo');
alert(combo.getValue());
}
}]
});
form.show();
}
});

Related

Inline style instead of quill editor inbuilt classes as classes are not available at the time to render HTML

I am using ngx-quill editor as my rich text editor in my angular project. So that I can save HTML generated by it in DB and then render it on different browsers as innerHTML. As it is not using inline CSS and there is a class attribute to style the HTML which refers to the inbuilt classes of this editor. I want to render this HTML on the platform where these inbuilt-classes are not available.
How to render the HTML on the page where these inbuilt classes are not available?
OR
Is there any way to convert these classes into inline styles?
OR
and if any other options to render HTML saved by this editor with the styling applied to it?
Any help would be appreciated
It's definitely possible. I managed to do it, but not in an Angular way, so in the end I am only using quill and not ngx-quill. I've been trying to figure out how to adjust ngx-quill to reflect this but with no success yet.
Anyway if you want to know how I am currently doing it.
First I create the html element:
<div id="editor"></div>
Then I add this to the top of my component:
import Quill from 'quill'
var DirectionAttribute = Quill.import('attributors/attribute/direction');
Quill.register(DirectionAttribute, true);
var AlignClass = Quill.import('attributors/class/align');
Quill.register(AlignClass, true);
var BackgroundClass = Quill.import('attributors/class/background');
Quill.register(BackgroundClass, true);
var ColorClass = Quill.import('attributors/class/color');
Quill.register(ColorClass, true);
var DirectionClass = Quill.import('attributors/class/direction');
Quill.register(DirectionClass, true);
var FontClass = Quill.import('attributors/class/font');
Quill.register(FontClass, true);
var SizeClass = Quill.import('attributors/class/size');
Quill.register(SizeClass, true);
var AlignStyle = Quill.import('attributors/style/align');
Quill.register(AlignStyle, true);
var BackgroundStyle = Quill.import('attributors/style/background');
Quill.register(BackgroundStyle, true);
var ColorStyle = Quill.import('attributors/style/color');
Quill.register(ColorStyle, true);
var DirectionStyle = Quill.import('attributors/style/direction');
Quill.register(DirectionStyle, true);
var FontStyle = Quill.import('attributors/style/font');
Quill.register(FontStyle, true);
var SizeStyle = Quill.import('attributors/style/size');
Quill.register(SizeStyle, true);
And then in my init method I declare it:
ngOnInit() {
this.editor = new Quill('#editor', {
modules: {
'toolbar': [
[{ 'font': [] }, { 'size': [] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'color': [] }, { 'background': [] }],
[{ 'script': 'super' }, { 'script': 'sub' }],
[{ 'header': '1' }, { 'header': '2' }, 'blockquote', 'code-block'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }],
['direction', { 'align': [] }],
['link', 'image', 'video']
]
},
theme: 'snow'
})
}
And then wherever I want to read the content:
this.email.message = this.editor.root.innerHTML
Of course this is not ideal at all, and it's a lot of code that I prefer to have inside a component. Maybe somebody else can help out squeezing this in a component

Visjs timeline edit content item template

I'd like to be able to edit the content attribute of visjs timeline items in the timeline itself. However, when I use an input as part of a template, it doesn't appear to receive any mouse events; I can't click in it and type anything, and clicking buttons doesn't work, either. Buttons appear to get the mouseover event, though:
function test(item) {
alert('clicked');
}
var options = {
minHeight: '100%',
editable: true,
moveable: false,
selectable: false,
orientation: 'top',
min: new Date('2015-01-01'),
max: new Date('2015-12-31'),
zoomMin: 1000 * 4 * 60 * 24 * 7,
margin: {
item: 10,
axis: 5
},
template: function(item) {
return '<div onClick="test"><input value="click in the middle"></input><button onClick="test">test</button></div>'
}
};
/* create timeline */
timeline.on('click', function (properties) {
var target = properties.event.target;
if(properties.item) properties.event.target.focus();
});
https://codepen.io/barticula/pen/EpWJKd
Edit: Code above CodePen example have been updated to use the click event to focus on the input, but all other normal mouse behavior is missing. Keyboard events appear to function normally.
To get a reaction with a click on a timeline element, you can use the library's own events (see events on doc and this exemple on website).
On your example, you could do something like this among other possible solutions in pure javascript including...
// Configuration for the Timeline
var options = {
minHeight: '100%',
editable: true,
moveable: false,
selectable: false,
orientation: 'top',
min: new Date('2015-01-01'),
max: new Date('2015-12-31'),
zoomMin: 1000 * 4 * 60 * 24 * 7,
margin: {
item: 10,
axis: 5
},
template: function(item) {
return '<div id="test-div"><input placeholder="hey" type="text" id="inputTest" ><button id="test-button">test</button></div>'
}
};
// Create a Timeline
var timeline = new vis.Timeline(container, null, options);
timeline.setGroups(groups);
timeline.setItems(items);
timeline.on('click', function (properties) {
var target = properties.event.target;
if(properties.item) alert('click on' + target.id);
});
UPDATED
It is difficult to know exactly what you want to do because there are several possible solutions anyway.
Eventually, I propose another snippet below and a codepen updated.... but will it meet your need, not sure ?
2nd UPDATE (for another work track, see comments)
// Configuration for the Timeline
var options = {
minHeight: '100%',
editable: true,
moveable: false,
selectable: false,
orientation: 'top',
margin: {
item: 10,
axis: 5
},
template: function(item) {
return '<div><input placeholder="edit me..." type="text"></input><button>send value</button></div>'
}
};
// Create a Timeline
var timeline = new vis.Timeline(container, null, options);
timeline.setGroups(groups);
timeline.setItems(items);
timeline.on('click', function(properties) {
var target = properties.event.target;
var item = items.get(properties.item);
console.log(properties.event);
// if (properties.item && target.tagName === "DIV") focusMethod(target);
if (properties.item && target.tagName === "INPUT") target.focus();
if (properties.item && target.tagName === "BUTTON") getInputValue(item, target);
});
focusMethod = function getFocus(target) {
// target.insertAfter("BUTTON");
target.firstChild.focus();
}
getInputValue = function getValue(item, target) {
target.focus();
var inputValue = (target.parentNode.firstChild.value) ? target.parentNode.firstChild.value : "no value entered ";
alert("Input value : " + inputValue + " => send by: " + item.content)
}

Why doesn't ui-grid in Angular Meteor show its data when filter is activated?

Hello I have a problem
Working:
Meteor
Angular Meteor
ui-grid
I follow the plunker example in documentation ui-grid link
The problem is that the data don't show when filters are activated.
I have no errors in console.
I put my code:
html file
<button id='toggleFiltering' ng-click="inventario.toggleFiltering()" class="btn btn-success">Toggle Filtering</button>
<div id="grid1" ui-grid="inventario.gridOptions" class="grid"></div>
js file
class Inventario {
constructor($scope, $reactive, $uibModal, $http, uiGridConstants) {
'ngInject';
$reactive(this).attach($scope);
this.$uibModal = $uibModal;
var today = new Date();
var nextWeek = new Date();
this.highlightFilteredHeader = (row, rowRenderIndex, col, colRenderIndex) => {
if( col.filters[0].term ){
return 'header-filtered';
} else {
return '';
}
};
this.gridOptions = {
enableFiltering: true,
onRegisterApi: (gridApi) => {
this.gridApi = gridApi;
},
columnDefs: [
// default
{ field: 'name', headerCellClass: this.highlightFilteredHeader },
// pre-populated search field
{ field: 'gender', filter: {
term: '1',
type: uiGridConstants.filter.SELECT,
selectOptions: [ { value: '1', label: 'male' }, { value: '2', label: 'female' }, { value: '3', label: 'unknown'}, { value: '4', label: 'not stated' }, { value: '5', label: 'a really long value that extends things' } ]
},
cellFilter: 'mapGender', headerCellClass: this.highlightFilteredHeader },
// no filter input
{ field: 'company', enableFiltering: false, filter: {
noTerm: true,
condition: (searchTerm, cellValue) => {
return cellValue.match(/a/);
}
}},
// specifies one of the built-in conditions
// and a placeholder for the input
{
field: 'email',
filter: {
condition: uiGridConstants.filter.ENDS_WITH,
placeholder: 'ends with'
}, headerCellClass: this.highlightFilteredHeader
},
// custom condition function
{
field: 'phone',
filter: {
condition: (searchTerm, cellValue) => {
var strippedValue = (cellValue + '').replace(/[^\d]/g, '');
return strippedValue.indexOf(searchTerm) >= 0;
}
}, headerCellClass: this.highlightFilteredHeader
},
// multiple filters
{ field: 'age', filters: [
{
condition: uiGridConstants.filter.GREATER_THAN,
placeholder: 'greater than'
},
{
condition: uiGridConstants.filter.LESS_THAN,
placeholder: 'less than'
}
], headerCellClass: this.highlightFilteredHeader},
// date filter
{ field: 'mixedDate', cellFilter: 'date', width: '15%', filter: {
condition: uiGridConstants.filter.LESS_THAN,
placeholder: 'less than',
term: nextWeek
}, headerCellClass: this.highlightFilteredHeader
},
{ field: 'mixedDate', displayName: "Long Date", cellFilter: 'date:"longDate"', filterCellFiltered:true, width: '15%',
}
]
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.success((data) => {
this.gridOptions.data = data;
this.gridOptions.data[0].age = -5;
data.forEach( function addDates( row, index ){
row.mixedDate = new Date();
row.mixedDate.setDate(today.getDate() + ( index % 14 ) );
row.gender = row.gender==='male' ? '1' : '2';
});
});
this.toggleFiltering = () => {
this.gridOptions.enableFiltering = !this.gridOptions.enableFiltering;
this.gridApi.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
};
}
}
const name = 'inventario';
// Módulo
export default angular
.module(name, [
uiRouter,
EditarArticulo
])
.component(name, {
templateUrl: `imports/ui/components/${name}/${name}.html`,
controllerAs: name,
controller: Inventario
})
.config(config)
.filter('mapGender', function() {
var genderHash = {
1: 'male',
2: 'female'
};
return function(input) {
if (!input){
return '';
} else {
return genderHash[input];
}
};
});
Given that everything seems to work when filtering is disabled, you must have a problem with the (multiple) filters you have declared.
It is most likely a combination of the filters that is excluding all of your data. Start by commenting out all of the filters (you should see all the data), and then re-introduce the filters one by one until you see the problem again.
This will narrow down the problem, and allow you to see which filter is wrong.

FullCalendar - Images as events

Looking to use Full Calendar and to include images as events and draggable. In short, would love to see how this example https://fullcalendar.io/js/fullcalendar-3.0.1/demos/external-dragging.html would work with small thumbnails instead of the text "My Event 1, My Event 2" etc. And have that image show up on the calendar.
Thanks in advance.
You can add any image url to your eventObject by adding the attribute "imageurl" inside of the events definition (if you just want the image, don't specify a title):
events: [
{
title : 'event',
start : '2016-10-12',
end : '2016-10-14',
imageurl:'img/edit.png', //you can pass the image url with a variable if you wish different images for each event
.
.
.
}
After that, you add the following code in the eventRender, which will add the image icon to the event (16 width and height is a good size for a thumbnail):
eventRender: function(event, eventElement) {
if (event.imageurl) {
eventElement.find("div.fc-content").prepend("<img src='" + event.imageurl +"' width='16' height='16'>");
}
},
For further details refer to this question: Add Icon(s) in first line of an event (fullCalendar)
In version Fullcalendar 5 or newer eventRender is no longer used, instead used eventContent
Full code:
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
events: [
{
title: '',
start: '2020-09-02',
image_url: 'images/demo/event-calendar-1.png',
},
{
title: '',
start: '2020-09-02',
image_url: 'images/demo/event-calendar-2.png',
},
{
title: 'Event',
start: '2020-09-17',
image_url: 'images/demo/event-calendar-1.png',
},
{
title: '',
start: '2020-09-19',
image_url: 'images/demo/event-calendar-3.png',
},
{
title: 'Hello',
start: '2020-09-28'
},
],
eventContent: function(arg) {
let arrayOfDomNodes = []
// title event
let titleEvent = document.createElement('div')
if(arg.event._def.title) {
titleEvent.innerHTML = arg.event._def.title
titleEvent.classList = "fc-event-title fc-sticky"
}
// image event
let imgEventWrap = document.createElement('div')
if(arg.event.extendedProps.image_url) {
let imgEvent = '<img src="'+arg.event.extendedProps.image_url+'" >'
imgEventWrap.classList = "fc-event-img"
imgEventWrap.innerHTML = imgEvent;
}
arrayOfDomNodes = [ titleEvent,imgEventWrap ]
return { domNodes: arrayOfDomNodes }
},
});
calendar.render();
});

JQGrid Inline Editing : Filter subcategory dropdown list based on another category dropdown

I have a category and a subcategory column in a Jqgrid. I have enabled inline editing, both category and subcategory are dropdownlists columns (edittype:'select'). I need to filter the subcategory list based on the selected category. I wonder how can I acheive this functionlity?
I tried the below event but its not working for me
afterEditCell: function(rowid, celname, value, iRow, iCol) {
//to do here
}
the above event doesn't get fired. my all column are editable
Thanks,
This question will be often asked. So I wrote a small code example which demonstrate how to implement such scenario with local data only (for jqGrid starting with 3.7.x). For data editing (inline editing) I use here the double-click event. The modified data will be saved after pressing of the "enter" key. For the filling of select elements I use ids. If you prefer use texts of the categories and subcategories instead you should remove formatter:'select' and make the corresponding changes in building of <option> elements (see code of dataEvents event handler).
var categories = ["sport", "science"];
var subcategories = ["football", "formel 1", "physics", "mathematics"];
var mydata = [
{Name:"Lukas Podolski", Category:0, Subcategory:0},
{Name:"Michael Schumacher", Category:0, Subcategory:1},
{Name:"Albert Einstein", Category:1, Subcategory:2},
{Name:"Blaise Pascal", Category:1, Subcategory:3}
];
var subcategoriesOfCategory = [
["football", "formel 1"],
["physics", "mathematics"]
];
var grid = jQuery("#list").jqGrid({
data: mydata,
datatype: 'local',
colModel: [
{ name: 'Name', width: 200 },
{ name: 'Category', width: 200, editable:true, formatter:'select',
edittype:'select', editoptions: {
value: categories,
dataInit : function (elem) {
var v = $(elem).val();
grid.setColProp('Subcategory', {
editoptions:{value:subcategoriesOfCategory[v]}});
},
dataEvents: [
{ type: 'change',
data: { id: 7 },
fn: function(e) {
var v=$(e.target).val();
var sel = grid.getGridParam('selrow');
grid.setColProp('Subcategory', { editoptions:
{value:subcategoriesOfCategory[v]}});
var res = '';
var sc = subcategoriesOfCategory[v];
for (var i=0; i<sc.length; i++) {
res += '<option role="option" value="' + i + '">' +
sc[i] + '</option>';
}
$("select#"+sel+"_Subcategory").html(res);
}
}
]
}
},
{ name: 'Subcategory', width: 200, editable:true, formatter:'select',
edittype:'select', editoptions: {value: subcategories} }
],
onSelectRow: function(id) {
if (id && id !== lastSel) {
grid.restoreRow(lastSel);
lastSel = id;
}
},
ondblClickRow: function(id, ri, ci) {
if (id && id !== lastSel) {
grid.restoreRow(lastSel);
lastSel = id;
}
grid.editRow(id, true);
return;
},
editurl: 'clientArray',
sortname: 'Name',
viewrecords: true,
rownumbers: true,
sortorder: "desc",
pager: '#pager',
caption: "Inline Editing example"
}).navGrid('#pager', { edit: false, add: false, del: false,
search: false, view: false });
This example can be of cause modified for the case of building of select option from the server.

Resources