I am working on a plugin that will allow us to add block options to the ACF block system and save the fields in meta. The issue is I am really rusty with js and I am unable to figure out how to merge my loop into the wp.element.create system. I have included my javascript below with comments of what I am trying to accomplish. Any help on this is greatly appreciated.
jQuery(function(){
var el = wp.element.createElement,
Fragment = wp.element.Fragment
registerBlockType = wp.blocks.registerBlockType,
RichText = wp.editor.RichText,
BlockControls = wp.editor.BlockControls,
AlignmentToolbar = wp.editor.AlignmentToolbar,
InspectorControls = wp.editor.InspectorControls;
var withInspectorControls = wp.compose.createHigherOrderComponent( function( BlockEdit ) {
return function( props ) {
// Set data if it does not exist - needed when new page is created
if(props.attributes.data === undefined){ props.attributes.data={}; }
// begin creating the return element
var elm = el(
Fragment,
{},
el( BlockEdit, props ),
el( InspectorControls, {},
el( PanelBody, { title: 'Accordion Options' },
// THIS IS WHERE THE ADDED ELEMENTS WILL GO
)
);
$.each(fields, function( key, field ) {
switch(field.type){
case 'text':
var optionField = el( TextControl, {
label: field.label,
help: field.instructions,
onChange: function(value){
textField=value;
props.setAttributes( { textField: value } );
}
});
// ADD optionField TO elm ABOVE CORRECTLY
break;
default: continue;
}
});
return elm;
};
}, 'withInspectorControls' );
wp.hooks.addFilter( 'editor.BlockEdit', 'acf/accordion', withInspectorControls );
}
Related
I'm probably not using promises correctly, but I'm calling a service (defined in a separate factory) into my controller like so,
_.each( $scope.aap.idList, function( id ){
MyService.getItems( $stateParams.name, id ).$promise.then(
function( scan ){
if( scan.length !== 0){
addToList( scan );
}
})
});
var addToList = function ( item ) {
$scope.aap.scans.push( _.clone( item ) );
return $scope.aap.scans;
};
The service is defined as:
service.getItems = function ( name, id ) {
var Items = $resource( '/proj/rs/pr/elems/getItems', {
id: Id,
name: name
}, {
query: {
method: 'GET',
isArray: true,
transformResponse: function ( scans ) {
var items = angular.fromJson( scans );
_.each( items, function ( scanItem ) {
scanItem.checked = false;
} );
return items;
}
}
} );
return Items.query();
Now, in MyService.getItems I can add a console.log( scan ) and see the appropriate objects being passed through, but it won't add these items to my list. Is there some other way I should be going about this?
Hello I'm parsing some data from my database into a table using aui-datatable plugin however I would like to add some basic sorting in my columns. Bellow you may see the function "renderProducts" which renders the data-table. Furthermore bellow is a sample column object that is being passed into the table renderer.
var API= (function(Y){
var settings = {
serviceURL : null
};
var getServiceAttribute = function( attribute ) {
return '_openpimadmin_WAR_OpenTest_' + attribute;
}
var getServiceURL = function( service ) {
return settings.serviceURL + '&p_p_resource_id=' + service;
};
var service = function( service, dataSet, handlers ){
var serviceData = {};
var serviceHandlers = {
start : function(){},
success : function(){},
failure : function(){},
end : function(){}
};
for (prop in dataSet) {
serviceData[getServiceAttribute(prop)] = dataSet[prop];
}
for (prop in handlers) {
if ( serviceHandlers.hasOwnProperty(prop) && typeof handlers[prop] === 'function') {
serviceHandlers[prop] = handlers[prop];
}
}
Y.io(
getServiceURL( service ),
{
method : 'POST',
data : serviceData,
on : {
start : function( transactionID ) {
serviceHandlers.start(transactionID);
},
success : function( transactionID, response ) {
var parsed = Y.JSON.parse(response.responseText);
if (parsed.success === true){
serviceHandlers.success( transactionID, parsed );
} else {
console.log('Service [' + service + '] error: ' + parsed.error);
}
},
failure : function( transactionID, response ) {
serviceHandlers.failure( transactionID, response );
},
end : function( transactionID ) {
serviceHandlers.end( transactionID );
}
}
}
);
}
return {
services : {
getProducts : function( dataSet, handlers ){
dataSet = dataSet || {};
handlers = handlers || {};
service( 'getProducts', dataSet, handlers );
},
getProductsTableAttributeHeaders : function( dataSet, handlers) {
dataSet = dataSet || {};
handlers = handlers || {};
service( 'getProductsTableAttributeHeaders', dataSet, handlers );
},
},
views : {
renderProducts : function( el, columns, dataSet ) {
Y.one(el).get('childNodes').remove();
new Y.DataTable.Base({
columnset : columns,
recordset : dataSet,
width: '100%'
}).render(el);
}
},
get : function( prop ) {
return settings[prop];
},
set : function( options ) {
settings = Y.merge( settings, options );
}
};
})( YUI().use('node', 'io', 'aui-datatable', 'datatable-sort', function(Y){return Y;}) );
Column object:
Object {key: "name", label: "Όνομα", allowHTML: true, emptyCellValue: "<em>(not set)</em>", sortable: true}
The issue I'm facing is that sorting is nowhere to be seen, columns dont seem interactive and the user is not able to sort them, although the table is being rendered fine.
Thank you in advance.
PS: I'm new to YUI().
You need to make sure that sortable: true set for column that need sorting.
Here is a real world example with sorting feature
It seems this was the problem:
new Y.DataTable.Base({
columnset : columns,
recordset : dataSet,
width: '100%'
}).render(el);
Should have been like this:
new Y.DataTable({
columnset : columns,
recordset : dataSet,
width: '100%'
}).render(el);
I've been using javascript for years, and gotten pretty good at it since I started a web development job, but working with node on a personal project I am having issues.
I create an object
;( function( undefined ) {
'use strict';
var scrape = {
data : {},
scrapers: [],
init : function( coins, exchanges, trade_paths ) {
scrape.start_time = new Date().getMilliseconds();
// Load events
var Event = require( 'events' );
// Add an eventEmitter to process
process.event = new Event.EventEmitter()
// Now we can load any modules, now that global process is modified ;)
//require( './bter.js' );
exchanges.forEach( function( exchange ) {
console.log( exchange.name + '.js' );
require( exchange.name.toLower() + '.js' );
} );
// Trigger the preload event
process.event.emit( 'scraper::init', coins );
// Response to all modules processes
process.event.on( 'scraper::add', scrape.add );
},
add : function( module ) {
scrape.data[module.name] = module.data;
}
};
// Get list of exchanges, coins, and trade paths
var sql_data = {
sql : {},
db : {},
coins : [],
exchanges : [],
trade_paths : [],
init : function() {
sql_data.sql = require( 'mysql' );
sql_data.db = sql_data.sql.createConnection( {
host : '127.0.0.1',
user : 'root',
password : ''
} );
sql_data.db.connect();
// Get coin list
sql_data.db.query('SELECT * FROM `node`.`coins` WHERE active=true', function(err, rows, fields) {
if( typeof rows !== 'undefined' ) {
sql_data.coins = rows;
}
// Oddly, if no error, its equal to null.
if( err !== null ) {
console.log( err );
}
} );
// Get exchange list
sql_data.db.query( 'SELECT * FROM `node`.`exchanges` WHERE active=true', function( err, rows, fields ) {
if( typeof rows !== 'undefined' ) {
sql_data.exchanges = rows;
}
if( err !== null ) {
console.log( err );
}
} );
// Get trade paths
sql_data.db.query( 'SELECT * FROM `node`.`trade_paths` WHERE active=true', function( err, rows, fields ) {
if( typeof rows !== 'undefined' ) {
sql_data.trade_paths = rows;
}
if( err !== null ) {
console.log( err );
}
} );
// Close connection to the database
sql_data.db.end();
}
};
sql_data.init();
// Start scraping
scrape.init( sql_data.coins, sql_data.exchanges, sql_data.trade_paths );
} () );
object.x is not accessible. Not even within object itself. I don't know what to do or how to fix this.
Your scrape.init function is called before you received data from mysql. You need to call it inside sql_data.init callback (which you can safely call in third .query() since mysql queries are executed sequentially per connection).
I would like to run some specific code around put() and add() for Dojo stores.
The problem I am having is that for JSON REST stores, in JsonRest.js add() is just a function that calls put():
add: function(object, options){
options = options || {};
options.overwrite = false;
return this.put(object, options);
},
So, if I use aspect.around() with add(), my code ends up being executed twice IF I apply my code to stores created with a store that implements add() as a stub to put().
Please note that I realise that most stores will do that. I just want my solution to be guaranteed to work with any store, whether there is method nesting or not.
Dojo's own Observable.js has the same problem. This is how they deal with it:
function whenFinished(method, action){
var original = store[method];
if(original){
store[method] = function(value){
if(inMethod){
// if one method calls another (like add() calling put()) we don't want two events
return original.apply(this, arguments);
}
inMethod = true;
try{
var results = original.apply(this, arguments);
Deferred.when(results, function(results){
action((typeof results == "object" && results) || value);
});
return results;
}finally{
inMethod = false;
}
};
}
}
// monitor for updates by listening to these methods
whenFinished("put", function(object){
store.notify(object, store.getIdentity(object));
});
whenFinished("add", function(object){
store.notify(object);
});
whenFinished("remove", function(id){
store.notify(undefined, id);
});
My question is: is there a simple, "short" way to change my existing code so that it checks if it's within a method, and avoid running the code twice?
I gave it a go, but I ended up with clanky, hacky code. I am sure I am missing something...
Here is my existing code:
topic.subscribe( 'hotplate/hotDojoStores/newStore', function( storeName, store ){
aspect.around( store, 'put', function( put ){
return function( object, options ){
return when( put.call( store, object, options ) ).then( function( r ) {
var eventName;
var identity = store.idProperty;
eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate';
topic.publish( eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false );
} );
}
});
aspect.around( store, 'add', function( add ){
return function( object, options ){
return when( add.call( store, object, options ) ).then( function( r ) {
var identity = store.idProperty;
topic.publish('storeRecordCreate', null, { storeName: storeName, storeTarget: storeTarget, objectId: r[identity], object: object }, false } );
});
}
});
});
This is my attempt...
What I don't really "get" about my attempt is whether it's 100% safe or not.
If store.add() is called twice in a row, is is ever possible that inMethod is set to true by the first call, and that the second add() call then finds it already set to true because the first one hasn't managed to set it to false yet?
This would only really be possible if nextTick() is called in between the two calls I assume?
Or am I just completely confused by it all? (Which is very possible...)
topic.subscribe( 'hotplate/hotDojoStores/newStore', function( storeName, store ){
var inMethod;
aspect.around( store, 'put', function( put ){
return function( object, options ){
if( inMethod ){
return when( put.call( store, object, options ) );
} else {
inMethod = true;
try {
return when( put.call( store, object, options ) ).then( function( r ) {
var eventName;
var identity = store.idProperty;
eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate';
topic.publish( eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false );
});
} finally {
inMethod = false;
}
}
}
});
aspect.around( store, 'add', function( add ){
return function( object, options ){
if( inMethod ){
return when( add.call( store, object, options ) );
} else {
inMethod = true;
try {
return when( add.call( store, object, options ) ).then( function( r ) {
var identity = store.idProperty;
topic.publish('storeRecordCreate', null, { type: 'storeRecordCreate', storeName: storeName, objectId: r[identity], object: object }, false );
});
} finally {
inMethod = false;
}
}
}
});
aspect.around( store, 'remove', function( remove ){
return function( objectId, options ){
return when( remove.call( store, objectId, options ) ).then( function( r ) {
topic.publish('storeRecordRemove', null, { type: 'storeRecordRemove', storeName: storeName, objectId: objectId }, false );
});
};
});
});
I have a backbone.js model similar to the one shown below.
Filters = Backbone.Model.extend({
defaults : {
title: [ ["title1", "easy"], ["title2", "hard"] ]
}
});
I'm trying to add an element to the first-level array, such that the model then becomes:
Filters = Backbone.Model.extend({
defaults : {
title: [ ["title1", "easy"], ["title2", "hard"], ["title3", "medium"] ]
}
});
The code I have right now is this:
function setFilters() {
var options = {};
for (var facet in facets) {
for (var facetKey in facets[facet]) {
if (!filterExists(facetKey)) {
options[facetKey] = new Array(new Array(facets[facet][facetKey], "equals"));
}
else {
(filters[facetKey]).push(new Array(facets[facet][facetKey], "equals"));
}
}
}
filters.set(options);
}
The function filterExists simply checks if the key "title" is present in the model. When I run this, it says that filters[facetKey] is undefined. But isn't this the first-level array I need to push my element into?
You can access model attributes with .get() and .set() functions, or directly via the .attributes property:
http://documentcloud.github.com/backbone/#Model-attributes
var filters = new Filters();
filters.attributes.facetKey.push( [...] );
OR
filters.set('facetKey', ( filters.get('facetKey') || []).concat([...]));
Anyway, here is your transformed function which may or may not work:
function setFilters() {
for (var facet in facets) {
for (var facetKey in facets[facet]) {
var f = [ facets[facet][facetKey], "equals" ];
if( filterExists(facetKey)) {
// OR: if( filters.attributes[ facetKey ]){
filters.attributes[ facetKey ].push( f );
}else{
filters.attributes[ facetKey ] = [ f ];
}
}
}
// trigger change event for all attributes
filters.set( filters.attributes );
}
Bonus:
(filters.attributes[ facetKey ] = filters.attributes[ facetKey ] || [] ).push(f);