Please forgive me if this has ever been asked before, it's very hard to search for since the operative word is 'this'.
I have a click event bound to a set of divs with the same class, each one needs the same behavior. In jQuery, I would simply use $(this) to reference the clicked element. I can't seem to figure out how to get CakePHP to use $(this) as the update element.
My code: (the 'update' param is the one in question)
$this->Js->get('.bookmark')->event('click',
$this->Js->request(
array('controller' => 'bookmarks', 'action' => 'add', $event['Event']['id']),
array('async' => true, 'update' => 'this')
)
);
Thank you
My personal opinion - don't use the CakePHP JsHelper. Don't get me wrong, I love CakePHP and am a CakePHP fanboy, but - in some cases it's just easier to use the "normal" way.
As an example, the HTML helper can create divs too, but I've never found the reason to use it over just typing <div>.
I've used this before for select lists (I modified it for your example, so I'm not 100% sure it works), I don't see why it wouldn't work for click
Put this at the bottom of the view
$this->Js->get('#addBookmarkDiv')->event('click', //put the div name that contains the input you're checking to see if it's clicked
$this->Js->request(array(
'controller'=>'bookmarks',
'action'=>'add'
), array(
'update'=>'#putdivhere', //div you want to update, possibly a div that displays bookmarks?
'async' => true,
'method' => 'post',
'dataExpression'=>true,
'data'=> $this->Js->serializeForm(array(
'isForm' => false,
'inline' => true
))
))
);
Now, in your controller do what you have to do, and add the following
function add(){
//do what ever it is you want to do with the sent data
$this->set('bookmarks',$bookmarks);
$this->layout = 'ajax';
}
Then, create a view for add with something like.
//add.ctp
<?php foreach ($bookmarks as $bookmark): ?>
<li><?php echo $bookmark; ?></li
<?php endforeach; ?>
Well, it looks like I was overlooking that fact that I could embed javascript in the JsHelper functions. That and the fact that $(this) is out of scope inside the $.ajax function. So, this is the solution that worked for me. As you can see, the second parameter to the event method is a mixture of javascript and PHP, and it's strung together in the first instance using concatenation.
$this->Js->get('.bookmark')->event('click',
'var el = $(this);'.
$this->Js->request(
array('controller' => 'bookmarks', 'action' => 'add', $event['Event']['id']),
array('async' => true, 'complete' => '$(el).addClass("bookmarked")')
)
);
Related
I have an old wordpress plugin built to show latest posts of choice. The plugin uses a shortcode with options. Now I am converting the plugin little bit so that it can be used as a gutenberg block. I kept the php code intact and trying to create a block which will have some settings (right side setting box for block). I don't want to show the posts in block editor like other blocks instead I will just show the data in frontend. So in admin, nothing will be visible rather than a placeholder text and the settings. In plugin's init.php I have this code (Please ignore coding mistakes here, I just put some part to get the idea):
final class Dcposts {
function dcposts_block_assets() {
register_block_type(
'dc/block-dcposts', array(
'style' => 'dcposts-style-css',
'editor_script' => 'dcposts-block-js',
'editor_style' => 'dcposts-block-editor-css',
'render_callback' => array($this, 'mytest')
)
);
}
public function mytest($attributes) {
return '[some_shortcode]'; // I will generate a dynamic shortcode with $attributes
}
}
This works fine. If I add the block, it shows the posts front-end. But I get an error message in admin: "Updating failed. The response is not a valid JSON response."while saving the page with the block; and also the shortcode executes in admin. How can I prevent this? Is this the right approach I am on? Please give me some idea.
The error message "Updating failed. The response is not a valid JSON response." occurs when your render_callback function returns different content than the Gutenberg Edit() function. For dynamic blocks, the save() function should return null.
The ServerSideRender block is ideal for migrating/integrating existing PHP functions into a Gutenberg block.
You are on the right path with registering your block dc/block-dcposts in PHP. Next, add a ServerSideRender component in the Edit function of your block declaration in JavaScript, eg:
index.js
import { registerBlockType } from '#wordpress/blocks';
import { __ } from '#wordpress/i18n';
import ServerSideRender from '#wordpress/server-side-render';
/**
* Registering our block in JavaScript
*/
registerBlockType('dc/block-dcposts', {
title: __('DCPosts', 'dc'),
description: __(
'What DCPosts does..',
'dc'
),
category: 'layout',
icon: 'star-filled',
edit: () => {
return (
<ServerSideRender
block="dc/block-dcposts"
/>
);
},
save: () => { return null } // Dynamic blocks should return null to avoid validation error.
});
plugin.php (simplified example)
function dc_block_dcposts($attributes){
return '<div>Dynamically rendered content</div>';
}
function dc_block_dcposts_init(){
register_block_type( 'dc/block-dcposts', array(
'render_callback' => 'dc_block_dcposts',
) );
};
add_action( 'init', 'dc_block_dcposts_init' );
Once you have the basic setup working, the next step could be migrating any attributes your PHP function requires. The attributes need to be defined in the block setup and then passed in via the ServerSideRender component to be recieved by your PHP function.
Halo, I using Yii2 and I get error while call a function in dropdown list.
This is my dropdown :
<?= $form->field($model, "jenis_manifest")->dropDownList([ 'Berangkat' => 'Berangkat', 'Pulang' => 'Pulang'], ['onchange' => 'fungsiUtama();', 'class' => 'form-control', 'prompt' => '-- Manifest --']) ?>
And this is my script :
<?php
$script = <<<JS
function fungsiUtama()
{
alert("Hello");
}
JS;
$this->registerJs($script);
?>
I also try with JsExpression base on this question, but still not working.
This is the error what I get :
Use
$this->registerJs($script, \yii\web\View::POS_END);
The last part means - add this script straightforward at the end of page.
Without the second function argument the default one is called -
\yii\web\View::POS_READY - which means - add this script wrapped in jQuery(document).ready() method that forces scripts to wait untill the page's DOM is fully loaded. Before that your script is unavailable and that is probably why you've got this error.
I have read a half-dozen examples of how to pass parameters to javascript and they all describe the process in a very similar manner but don't speak to one event: how does the javascript code actually get called? I have seen several examples where the code is tested in $document.ready, but can't get them to work.
Here is my php code:
$base_id = 'id_'.wp_create_nonce("postlister");
$url = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$parms = array(
'url' => $url,
'action' => $action,
'base_id' => base_id );
wp_localize_script(self::slug.'-postlister', 'postlister_parms', $parms);
And my jQuery code:
jQuery(document).ready(function (postlister_parms) {
if (postlister_parms !== undefined) {
var parms = postlister_parms;
$.diagnostic('postlister loaded');
}
});
When the page loads, there is a div generated were my code writes some additional html:
echo '<div id="'.$base_id.'"></div>';
produces:
<div id="id_c8aca14643"></div>
The footer contains:
<script type="text/javascript" src="http://localhost/mkpusa.org/nw/wp-content/plugins/rhj4-postlister/js/postlister.js?ver=3.9.2"></script>
When the jQuery code executes, postlister_parms is a function:
postlister_parms: function (a,b){return new n.fn.init(a,b)}
But postlister_parms.url, .action and .base_id are all undefined.
Please help me spot what I am missing.
The resulting code should look something like this:
var postlister_parms = {"url":"the_url","action":"the_action","base_id":"the_baseid"};
Make sure that the script with the handle self::slug.'-postlister' is enqueued before you call wp_localize_script
Have you read the Notes section of the documentation The call to wp_enqueue_script and wp_localize_script should be in a wp_enqueue_scripts action and the script should be enqueued before it is localized. That being true, it should work
Is there any way to add function to JSON object with php?
i have an array in php like this :
$aoData = array(
array('name' => 0, 'value' => "id"),
array('name' => 1, 'value' => "title"),
array('name' => 2, 'value' => "cat"),
array('name' => 3, 'value' => "img"),
array('name' => 4, 'value' => "des"));
and i want add a function like this:
array('name' => 5, 'value' => function(){return "hi"})
and use this function in my jquery.
is there any way for this?
Update
in data table i need to set aoColumnDefs in php.
"aoColumnDefs":
[{
"aTargets": [ img ],
"mData": "thumb_img",
"mRender": function ( data, type, full )
return '<img src="../up/thumb/'+data+'">';
},
{etc}
]
so i need set function as a Json function or another way ...
JSON does not allow function definition for security and compatibility reasons, and as a proof, I don't see any other way than storing a string and use a form of eval (that is using eval or creating a Function with a body). I'd strongly recommend not to do it though.
In order for it to be JSON, and for any JSON library to work with it, no, it is not possible.
JSON is a language and platform independent, portable data serialization scheme and, therefore, has a limited set of things which can be represented within. Functions, given that they are language and platform specific, are not portable.
It is possible to use PHP to "manually" output a JavaScript object which has methods:
<?php
$foo = '{name: 5, value: function () { return "hi";}}'
?>
var js_object = <? echo $foo; ?>;
This is messy and error prone, however, and would not be JSON.
So yeah...
JS Object is not the same as JSON.
Some libs or frameworks will want to add functions to the JS Object.
For example primevue has a menu structure with functions in the Object:
const items = {
label: 'New',
icon: 'pi pi-plus',
command: (event) => {
// event.originalEvent: Browser event
// event.item: Menuitem instance
}
}
;
Nice, but what if you want this data provided from DB via php...?
this works:
const func = 'items.command = function(event){ console.log(event) }'
eval(func)
So we could do something with this.
This means doing something with the JSON when it is loaded into Javascript and turn some strings into functions with eval.
This is of course a security risk.
But somehow we'll need to change the JSON into a JS Object.
Better maybe is to not have info of the end platform in the DB.
The solution I'm using is that I'm pre-defining what commands can be added to the JS Object and use codes to tell the reader what I want added.
switch (add) {
case '[login]':
items.command: () => {
auth.destroyToken()
this.$router.push({ name: 'login' })
}
break;
}
Not as "free", but for security that's a good thing.
You can't add the function as value, but you can add the return value of the function as value of the json object.
So in the example you gave, the value will just be "hi" (if you type return correctly).
I don't see the reason for adding a function into a JSON object, because you can probebly do the same with JQuery and if you can't then use AJAX to get results from the serverside.
I am trying to disable the JavaScript when the user is using IE. Is there a way to accomplish this in template.php or a custom module?
As alternative to handling the content of $vars['scripts'], which is a string containing the HTML to output in the <head> tag, you could use the value returned from drupal_add_js(NULL, NULL, 'header'), which is similar to the following one:
$header_javascript = array(
'core' => array(
'misc/jquery.js' => array(
'cache' => TRUE,
'defer' => FALSE,
'preprocess' => TRUE,
),
'misc/drupal.js' => array(
'cache' => TRUE,
'defer' => FALSE,
'preprocess' => TRUE,
),
),
'module' => array(),
'theme' => array(),
'setting' => array(
array('basePath' => base_path()),
),
'inline' => array(),
);
The "module" index contains the reference to the JavaScript files added from the modules, "settings" contains all the JavaScript settings generally added by the modules, and "inline" contains inline JavaScript code.
It could help if you need to distinguish between the different JavaScript files, and (for example) not touch any JavaScript file that has been marked as "core."
The counterbalance is that to populate the content of $vars['scripts'] you need to duplicate part of the code used from drupal_get_js(). As you would need a customized code, you would not duplicate all the code of that function, but you still would duplicate part of it.
In Drupal 7, the variable $vars['scripts'] is not passed anymore to template_preprocess_page() (and similar preprocess functions implemented by modules or themes); it is passed to template_preprocess_html().
You can use the preprocess_page() hook in template.php.
function YOUR_THEME_preprocess_page(&$vars) {
if (isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false)) {
$vars['scripts'] = 'get a mac!';
}
}
Obviously you should do something more intelligent with the $vars['scripts'] content :)