I need to update a variable on submit inside tinymce window.
Here the tinymce code:
tinymce.PluginManager.add('tc_button',function(editor,url){
editor.addButton('tc_button',{
title: 'Images',
onclick: function(){
editor.windowManager.open({
title: 'Images',
buttons: [{text: 'Add Shortcode', onclick: 'submit'}, {text: 'Cancel', onclick: 'close'}],
body: [
{type: 'container',
label : 'Image URL',
items: [
{type: 'textbox', id: 'image1', name : 'image1', style:'width:270px'},
{type: 'listbox', id: 'effect1', name: 'effect1', style:'margin-left:10px'},
]}
],
onsubmit: function(e) {
jQuery.post(ajax_url,
{
action: 'save_image',
image: imageData,
}
),
function ( data ){
var jsonData = tryParseJSON( data );
if ( jsonData !== false ) {
var new_url = jsonData.attachment_url;
jQuery('#image1').attr('src', new_url);
}
};
editor.insertContent('[shortcode image1="' + e.data.image1 + '"]' );
}
});
}
});
});
I need to run jQuery('#image1').attr('src', new_url) inside ajax call before editor.insertContent is added inside editor. How can i set it so to wait ajax call is ended and #image1 source is updated with ajax result value?
Thanks in advance.
You need to call editor.insertContent('[shortcode image1="' + e.data.image1 + '"]' ); inside call back function after jQuery('#image1').attr('src', new_url);
tinymce.PluginManager.add('tc_button', function(editor, url) {
editor.addButton('tc_button', {
title: 'Images',
onclick: function() {
editor.windowManager.open({
title: 'Images',
buttons: [{
text: 'Add Shortcode',
onclick: 'submit'
}, {
text: 'Cancel',
onclick: 'close'
}],
body: [
{
type: 'container',
label: 'Image URL',
items: [{
type: 'textbox',
id: 'image1',
name: 'image1',
style: 'width:270px'
},
{
type: 'listbox',
id: 'effect1',
name: 'effect1',
style: 'margin-left:10px'
},
]
}
],
onsubmit: function(e) {
jQuery.post(ajax_url, {
action: 'save_image',
image: imageData,
}),
function(data) {
var jsonData = tryParseJSON(data);
if (jsonData !== false) {
var new_url = jsonData.attachment_url;
jQuery('#image1').attr('src', new_url);
}
editor.insertContent('[shortcode image1="' + e.data.image1 + '"]');
};
}
});
}
});
});
Related
I have a list of grids that can change their data in form by end-user.
Finally, I want to sync all the grids by clicking the button, then an operation is performed.
I wrote the code below:
$.when.apply(
Ext.ComponentQuery.query('grid')
.forEach(function(item) {
if (item.getXType() == "grid") {
if (item.store.getNewRecords().length > 0 || item.store.getUpdatedRecords().length > 0 || item.store.getRemovedRecords().length > 0) {
item.store.sync();
}
}
})).then(function (results) {
//do something
});
Problem is here that store.sync() not waiting for callback.
What is the recommended way of doing this?
I do it with Promise like this:
// Sync grid data if exist dirty data
Promise.all(
Ext.ComponentQuery.query('grid')
.map(grid => grid.getStore())
.filter(s => (s.getNewRecords().length + s.getUpdatedRecords().length + s.getRemovedRecords().length) > 0)
.map(s => new Promise((resolve, reject) => {
s.sync({
success: () => { resolve(); },
failure: () => { reject(); }
});
}))
).then(() => {
//do something
});
You could use callback for your store.sync() method.
The callback function to be called upon completion of the sync. The callback is called regardless of success or failure and is passed the following parameters: (batch, options).
You could achieve your requirement like this
Take a blank array name before loop. like this var gridIds=[].
In side of loop before store.sync() push grid id in above array.
Now in callback function remove that grid id from above array and check condition array is blank then your all store sync response has came.
You can check here with working Fiddle
Note I have used dummy api. Please use your actual api.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('MyStore', {
extend: 'Ext.data.Store',
alias: 'store.mystore',
fields: ['name'],
autoLoad: true,
pageSize: 25,
remoteSort: true,
proxy: {
type: 'ajax',
method: 'POST',
api: {
read: 'data.json',
update: 'your_update_api',
create: 'your_create_api',
destroy: 'your_delete_api'
},
reader: {
type: 'json'
},
writer: {
type: 'json',
encode: true,
root: 'data'
}
},
});
Ext.define('MyGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.mygrid',
store: {
type: 'mystore'
},
height: 200,
border: true,
tools: [{
xtype: 'button',
iconCls: 'fa fa-plus-circle',
tooltip: 'Add New Record',
handler: function () {
let grid = this.up('grid'),
store = grid.getStore();
store.insert(0, {
name: 'Test ' + (store.getCount() + 1)
});
}
}],
columns: [{
text: 'Name',
dataIndex: 'name',
flex: 1
}]
});
Ext.create({
xtype: 'panel',
// title: 'Store sync example',
items: [{
xtype: 'mygrid',
title: 'Grid 1'
}, {
xtype: 'mygrid',
title: 'Grid 2'
}, {
xtype: 'mygrid',
title: 'Grid 3'
}, {
xtype: 'mygrid',
title: 'Grid 4'
}],
bbar: ['->', {
text: 'Submit Changes',
handler: function (btn) {
var panel = btn.up('panel'),
grids = panel.query('grid'),
gtidIds = [],
lenthCheck = function (arr) {
return arr.length > 0;
};
grids.forEach(function (grid) {
let store = grid.getStore();
if (lenthCheck(store.getNewRecords()) || lenthCheck(store.getUpdatedRecords()) || lenthCheck(store.getRemovedRecords())) {
panel.mask('Please wait...');
gtidIds.push(grid.getId());
store.sync({
callback: function () {
Ext.Array.remove(gtidIds, grid.getId());
if (gtidIds.length == 0) {
panel.unmask();
Ext.Msg.alert('Info', 'All grid store sync success.');
}
}
}, grid);
}
});
}
}],
renderTo: Ext.getBody(),
})
}
});
I would like to create checkbox in popup window using tinymce. I can create listbox in popup window but cannot create checkbox in it.
var tempGroups = ['Group1', 'Group2', 'Group3', 'Group4'];
var temp = [{
group: 'Group1',
title: 'Title1',
content: '<p>Content1</p>',
}, {
group: 'Group1',
title: 'Title1-1',
content: '<p>Content11</p>',
}, {
group: 'Group2',
title: 'Title2',
content: '<p>Content2</p>'
}, {
group: 'Group2',
title: 'Title2-1',
content: '<p>Content22</p>'
}, {
group: 'Group3',
title: 'Title3-1',
content: '<p>Content33</p>'
}, {
group: 'Group4',
title: 'Title4',
content: '<p>Content4</p>'
}, {
group: 'Group4',
title: 'Title4-1',
content: '<p>Content44</p>'
}];
var tempGroupName;
var menuItems = [];
function createTempMenu(editor) {
for (i = 0; i < tempGroups.length; i++) {
var tempArray = [];
tempArray[i] = [];
tempGroupName = tempGroups[i];
for (j = 0; j < temp.length; j++) {
if (temp[j].group == tempGroupName) {
tempArray[i].push({
text: temp[j].title,
content: temp[j].content,
// type: 'checkbox',
onclick: function () {
alert(this.settings.content);
}
});
}
}
menuItems[i] = {
text: tempGroupName,
menu: tempArray[i],
};
}
return menuItems;
}
tinymce.init({
selector: "textarea",
setup: function (editor) {
editor.addButton('button', {
type: 'menubutton',
text: 'button',
icon: false,
menu: [
{
text: 'Customer List',
onclick: function () {
editor.windowManager.open({
title: 'Customer Name',
width: 200,
height: 100,
items: [
{
type: 'listbox',
value: 0,
label: 'Section: ',
values: createTempMenu(editor),
body: [
{
type: 'checkbox',
label: 'Section: ',
// text: "new",
values: createTempMenu(editor),
}],
onsubmit: function (e) {
}
}]
});
}
}]
});
},
toolbar: " button "
});
Any help will be appreciated.
An old question just found it. If you're still looking for an answer you can refer to their reference Here it has further details
There's a type called checkbox in tinymce
{
type : 'checkbox',
name : 'choose the name',
label : 'choose a label',
text : 'the text near the checkbox',
checked : false
},
I have created a tabpanel, with images as titles, and a custom component as html. Those custom components use stores, but I'm having an error when updating a single variable (status), all the variables change. Here I show the code:
SelectableButtons component:
Ext.require('Cat3.view.fsm.data.ButtonsStore');
/**
* Selectable button with image
*/
Ext.define('Cat3.view.fsm.components.SelectableButtons', {
extend: 'Ext.view.View',
cls: 'selectable-buttons',
alias: 'widget.selectable-buttons',
tpl: [
'<tpl for=".">',
'<div class="thumb-wrap button button-{status}">',
'<img src="resources/images/cards/{type}/{status}/{name}.png">',
'<img src="resources/images/icons/icon_mandatory.png" class="button-tick button-tick-{status}">',
'</div>',
'</tpl>'
],
// Set both to false if you want single select
multiSelect: true,
simpleSelect: true,
trackOver: false,
itemSelector: 'div.thumb-wrap',
listeners: {
select: function(ths, record, eOpts) {
record.set('status', 'active');
debugAmenaButtonStatus(this);
},
deselect: function(ths, record, eOpts) {
record.set('status', 'passive');
},
selectionchange: function(selection) {
this.refresh();
},
containerclick: function(ths, e, eOpts) {
return false; // Stops the deselection of items
}
},
initComponent: function() {
var store = Ext.create('Cat3.view.fsm.data.ButtonsStore');
this.setStore(store);
this.callParent(arguments);
}
});
debugAmenaButtonStatus = function(ref) {
ref.up().up().items.items.forEach(function(tab) { // Tab
console.log(tab.items.items[0].getStore().data.items[0].data.status); // Amena Button Status
});
};
SelectableButtonsCarousel component (Tab panel). It uses another store but it isn't related:
var cardsImagePath = 'resources/images/cards/';
var ImageModel = Ext.define('ImageModel2', {
extend: 'Ext.data.Model',
fields: [{
name: 'name',
type: 'string'
}, {
name: 'type',
type: 'string'
}, {
name: 'status',
type: 'string'
}, ]
});
var store = Ext.create('Ext.data.Store', {
model: 'ImageModel2',
data: [{
name: 'amena',
type: 'operator',
}, {
name: 'movistar',
type: 'operator',
}, {
name: 'orange',
type: 'operator',
}, {
name: 'simyo',
type: 'operator',
}, {
name: 'yoigo',
type: 'operator',
}, {
name: 'vodafone',
type: 'operator',
}]
});
Ext.define('Cat3.view.fsm.components.SelectableButtonsCarousel', {
extend: 'Ext.tab.Panel',
xtype: 'basic-tabs',
cls: 'selectable-buttons-carousel',
alias: 'widget.selectable-buttons-carousel',
store: store,
resizeTabs: false,
defaults: {
bodyPadding: 10,
layout: 'fit'
},
require: [
'Cat3.view.fsm.components.SelectableButtons',
'Cat3.view.fsm.data.ButtonsStore'
],
titleTpl: function(info) {
return '<img src="resources/images/cards/operator/' + info.status + '/' + info.name + '.png">';
},
listeners: {
render: function(p) {
var tabpanel = this;
this.store.data.items.forEach(function(item, index) {
item.data.status = index === 0 ? 'active' : 'passive';
var buttons = new Cat3.view.fsm.components.SelectableButtons();
tabpanel.add(Ext.create('Ext.Panel', {
id: 'tab-' + index,
title: tabpanel.titleTpl(item.data),
items: [ buttons ],
cls: item.data.status,
info: item.data,
listeners: {
render: function(p) {
console.log('render');
}
}
}));
});
tabpanel.setActiveTab(0);
},
tabchange: function(tabPanel, newCard, oldCard, eOpts) {
newCard.info.status = 'active';
newCard.setTitle(this.titleTpl(newCard.info));
newCard.items.items[0].refresh();
if (oldCard) {
oldCard.info.status = 'passive';
oldCard.setTitle(this.titleTpl(oldCard.info));
}
}
}
});
SelectableButtons Store:
var ImageModel = Ext.define('ImageModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'type', type: 'string'},
{name: 'status', type: 'string'},
]
});
Ext.define('Cat3.view.fsm.data.ButtonsStore', {
extend: 'Ext.data.Store',
model: 'ImageModel',
data: [
{name: 'amena', type: 'operator', status: 'passive'},
{name: 'movistar', type: 'operator', status: 'passive'},
{name: 'orange', type: 'operator', status: 'passive'},
{name: 'simyo', type: 'operator', status: 'passive'},
{name: 'yoigo', type: 'operator', status: 'passive'},
{name: 'vodafone', type: 'operator', status: 'passive'}
],
listeners: {
datachanged: function() {
console.log('store data changed');
}
}
});
All works fine, but when I select a button of SelectableButtons (one tab), the same button of each tab changes its status, and only the one selected of the active tab has to change. Any ideas why? I've checked each store is created separately and that each store has a different id.
Just an idea, for a better guess I'd need to see it working best at http://fiddle.sencha.com:
If "select one selects all", my first idea is that all buttons are just one button referred to from all places. One instance with different names.
Notice the line on your Cat3.view.fsm.components.SelectableButtons view:
initComponent: function() {
var store = Ext.create('Cat3.view.fsm.data.ButtonsStore');
...
}
You might wanna change it to
initComponent: function() {
var store = new Ext.create('Cat3.view.fsm.data.ButtonsStore');
...
}
This will create a new instance of Data Store for your view.
I am using Jtable (Jquery based).
I have some trouble with the child table.
In the child table I added a new button in the toolbar.
With this new button in the toolbar, che close icon disappear, how can I fix it?
(if I remove the toolbar element the X of close button is correctly displayed).
$('#ListHeader').jtable({
title: 'ExpensesAccounts' ,
actions: {
listAction: function (postData, jtParams) {
return getListDataHeader();
}
},
fields: {
ID:{
key: true,
list:false
},
Details: {
title: '',
width: '5%',
sorting: false,
edit: false,
saveUserPreferences: false,
create: false,
display: function (headerData) {
//Create an image that will be used to open child table
var $img = $('<img src="../Images/viewDetails.png" width="20p" height="20p" title="View Details" />');
//Open child table when user clicks the image
$img.click(function () {
$('#ListHeader').jtable('openChildTable',
$img.closest('tr'),
{
title: headerData.record.Title + ' - Row' ,
saveUserPreferences: false,
paging: true,
pageSize: 3,
showCloseButton:true,
toolbar: {
items: [{
icon: '../scripts/jtable/themes/metro/add.png',
text: 'Add New Row',
click: function (headerID) {
window.location = "InsertRow.aspx";
}
}]
},
actions: {
listAction: function (postData, jtParams) {
return getListDataRow(headerData.record.ID, jtParams.jtStartIndex, jtParams.jtPageSize);
//return { "Result": "OK", "Records": [] };
},
deleteAction: function (postData) {
return deleteItem(postData, 'Expense Account Rows');
}
},
fields: {
HeaderID: {
type: 'hidden',
defaultValue: headerData.record.ID
},
ID: {
key: true,
create: false,
edit: false,
list: false
},
Title: {
title: 'Title',
width: '20%'
}
}
}, function (data) { //opened handler
data.childTable.jtable('load');
});
});
//Return image to show on the person row
return $img;
}
},
Title: {
title: 'Title'
},
Status: {
title: 'Status',
width: '8%'
}
}
});
$('#ListHeader').jtable('load');
Thanks,
Nk
please I'm trying to get a list of all the contacts on my phone with the following code.
var App = new Ext.Application({
name: 'SmsthingyApp',
useLoadMask: true,
launch: function () {
Ext.data.ProxyMgr.registerType("contactstorage",
Ext.extend(Ext.data.Proxy, {
create: function(operation, callback, scope) {
},
read: function(operation, callback, scope) {
},
update: function(operation, callback, scope) {
},
destroy: function(operation, callback, scope) {
}
})
);
Ext.regModel("contact", {
fields: [
{name: "id", type: "int"},
{name: "givenName", type: "string"},
{name: "familyName", type: "string"},
{name: "emails", type: "auto"},
{name: "phoneNumbers", type: "auto"}
]
});
Ext.regStore('contacts',{
model: "contact",
proxy: {
type: "contactstorage",
read: function(operation, callback, scope) {
var thisProxy = this;
navigator.contacts.find(
['id', 'name', 'emails', 'phoneNumbers', 'addresses'],
function(deviceContacts) {
//loop over deviceContacts and create Contact model instances
var contacts = [];
for (var i = 0; i < deviceContacts.length; i++) {
var deviceContact = deviceContacts[ i ];
var contact = new thisProxy.model({
id: deviceContact.id,
givenName: deviceContact.name.givenName,
familyName: deviceContact.name.familyName,
emails: deviceContact.emails,
phoneNumbers: deviceContact.phoneNumbers
});
contact.deviceContact = deviceContact;
contacts.push(contact);
}
//return model instances in a result set
operation.resultSet = new Ext.data.ResultSet({
records: contacts,
total : contacts.length,
loaded : true
});
//announce success
operation.setSuccessful();
operation.setCompleted();
//finish with callback
if (typeof callback == "function") {
callback.call(scope || thisProxy, operation);
}
},
function (e) { console.log('Error fetching contacts'); },
{multiple: true}
);
}
}
});
Ext.regModel('Sms', {
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
{ name: 'date', type: 'date', dateFormat: 'c' },
{ name: 'title', type: 'string' },
{ name: 'message', type: 'string' }
],
validations: [
{ type: 'presence', field: 'id' },
{ type: 'presence', field: 'title', message: 'Please select a contact for this sms.' }
]
});
Ext.regStore('SmsStore', {
model: 'Sms',
sorters: [{
property: 'date',
direction: 'DESC'
}],
proxy: {
type: 'localstorage',
id: 'sms-app-localstore'
},
getGroupString: function (record)
{
if (record && record.data.date)
{
return record.get('date').toDateString();
}
else
{
return '';
}
}
});
SmsthingyApp.views.ContactsList = new Ext.List({
id: 'ContactsList',
layout: 'fit',
store:'contacts',
itemTpl: '{givenName} {familyName}',
listeners: {'render': function (thisComponent)
{
SmsthingyApp.views.ContactsList.getStore().load();
}
},
onItemDisclosure: function (record) {
//Ext.dispatch({
// controller: SmsthingyApp.controllers.contacts,
// action: 'show',
// id: record.getId()
//});
}
});
SmsthingyApp.views.contactsListContainer = new Ext.Panel({
id: 'contactsListContainer',
layout: 'fit',
html: 'This is the sms list container',
items: [SmsthingyApp.views.ContactsList],
dockedItems: [{
xtype: 'toolbar',
title: 'Contacts'
}]
});
SmsthingyApp.views.smsEditorTopToolbar = new Ext.Toolbar({
title: 'Edit SMS',
items: [
{
text: 'Back',
ui: 'back',
handler: function () {
SmsthingyApp.views.viewport.setActiveItem('smsListContainer', { type: 'slide', direction: 'right' });
}
},
{ xtype: 'spacer' },
{
text: 'Save',
ui: 'action',
handler: function () {
var smsEditor = SmsthingyApp.views.smsEditor;
var currentSms = smsEditor.getRecord();
// Update the note with the values in the form fields.
smsEditor.updateRecord(currentSms);
var errors = currentSms.validate();
if (!errors.isValid())
{
currentSms.reject();
Ext.Msg.alert('Wait!', errors.getByField('title')[0].message, Ext.emptyFn);
return;
}
var smsList = SmsthingyApp.views.smsList;
var smsStore = smsList.getStore();
if (smsStore.findRecord('id', currentSms.data.id) === null)
{
smsStore.add(currentSms);
}
else
{
currentSms.setDirty();
}
smsStore.sync();
smsStore.sort([{ property: 'date', direction: 'DESC'}]);
smsList.refresh();
SmsthingyApp.views.viewport.setActiveItem('smsListContainer', { type: 'slide', direction: 'right' });
}
}
]
});
SmsthingyApp.views.smsEditorBottomToolbar = new Ext.Toolbar({
dock: 'bottom',
items: [
{ xtype: 'spacer' },
{
text: 'Send',
handler: function () {
// TODO: Send current sms.
}
}
]
});
SmsthingyApp.views.smsEditor = new Ext.form.FormPanel({
id: 'smsEditor',
items: [
{
xtype: 'textfield',
name: 'title',
label: 'To',
required: true
},
{
xtype: 'textareafield',
name: 'narrative',
label: 'Message'
}
],
dockedItems:[
SmsthingyApp.views.smsEditorTopToolbar,
SmsthingyApp.views.smsEditorBottomToolbar
]
});
SmsthingyApp.views.smsList = new Ext.List({
id: 'smsList',
store: 'SmsStore',
grouped: true,
emptyText: '<div style="margin: 5px;">No notes cached.</div>',
onItemDisclosure: function (record)
{
var selectedSms = record;
SmsthingyApp.views.smsEditor.load(selectedSms);
SmsthingyApp.views.viewport.setActiveItem('smsEditor', { type: 'slide', direction: 'left' });
},
itemTpl: '<div class="list-item-title">{title}</div>' +'<div class="list-item-narrative">{narrative}</div>',
listeners: {'render': function (thisComponent)
{
thisComponent.getStore().load();
}
}
});
SmsthingyApp.views.smsListToolbar = new Ext.Toolbar({
id: 'smsListToolbar',
title: 'Sent SMS',
layout: 'hbox',
items:[
{xtype:'spacer'},
{
id:'newSmsButton',
text:'New SMS',
ui:'action',
handler:function()
{
var now = new Date();
var smsId = now.getTime();
var sms = Ext.ModelMgr.create({ id: smsId, date: now, title: '', narrative: '' },'Sms');
SmsthingyApp.views.smsEditor.load(sms);
SmsthingyApp.views.viewport.setActiveItem('smsEditor', {type: 'slide', direction: 'left'});
}
}
]
});
SmsthingyApp.views.smsListContainer = new Ext.Panel({
id: 'smsListContainer',
layout: 'fit',
html: 'This is the sms list container',
dockedItems: [SmsthingyApp.views.smsListToolbar],
items: [SmsthingyApp.views.smsList]
});
SmsthingyApp.views.viewport = new Ext.Panel({
fullscreen: true,
layout: 'card',
cardAnimation: 'slide',
items:[
SmsthingyApp.views.contactsListContainer,
SmsthingyApp.views.smsListContainer,
SmsthingyApp.views.smsEditor
]
});
}
})
I'm using eclipse and LogCat tab keeps marking this red
02-08 11:11:58.741: E/Web Console(13886): Uncaught TypeError: Cannot read property 'contacts' of undefined at file:///android_asset/www/app.js:35
I'm guessing this has something to with why I can't see the contacts in the contactsListContainer.
Any help please?
I'm not a Sencha expert but I do know that this line:
var App = new Ext.Application({
will cause problems with PhoneGap as we also declare a variable called App. It would be better to change that line to be something like:
var myApp = new Ext.Application({
to avoid the name conflict.
If that doesn't resolve your problem I suggest you read over my post on searching contacts. I'd make sure I could successfully search for contacts before adding in Sencha.