I need to a custom jQuery function in my TYPO3 backend when Im opening the "Page"-view.
I added a hook for the preProcess
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']
['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']
['tx_dashboard'] =
\vendor\dashboard\Hooks\Backend\IconCorrection::class;
And in my IconCorrection I added
public function preProcess(PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row)
{
GeneralUtility::makeInstance(PageRenderer::class)
->addRequireJsConfiguration([
'paths' => [
'iconCorrection'=>'/typo3conf/ext/dashboard/Resources/Public/JavaScript/hidePreviewIcon.js',
],
'shim' => [
'iconCorrection' => ['jquery'],
],
]);
}
}
In my hidePreviewIcon.js I have a console.log
I want something like $(".btn").hide(); but for now just testing if the js is loaded.
In my dev-tools I see that the js was loaded, but the console.log wasnt executed.
What Im missing?
And can I just using addJsFile instead of addRequireJsConfiguration
Im using TYPO3 v8.7.2
EDIT:
I added
$renderer =\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Page\PageRenderer::class);
$renderer->addJsFile('/typo3conf/ext/trumpf_editordashboard/Resources/Public/JavaScript/hidePreviewIcon.js', 'text/javascript', false, false, '', true, '|', false, '');
to my preProcess()function.
Now the .js was loaded and executed a console.log();
But my
$(document).ready(){$(".btn").hide();
doesnt work. I think its executed too early
EDIT 2: Did the trick:
$(function(){
$('#typo3-contentIframe').ready(function(){
console.log("loaded");
$(".btn").hide();
});
});
Related
I am trying to add a from with a CKeditor widget imbedded via an AJAX request. The request itself works fine and returns the general partial view as I want it. Except for the Ckeditor widget, a normal textbox is return instead.
When the item is added to the group and the page is reloaded, the same partialView is being rendered (in a foreach with all group-items) and this time the CKeditor is nicely in place.
Posted my controller, initialization of the CKeditor and Scipt with AJAX request below. (The CKeditor is inlcuded in the _ContentItemHtml view)
I have taken a look at this, but I cannot call any CKeditor functions from JS since it is loaded as a widget.
Controller Action
public function actionCreateHtml($contentitemgroupid)
{
$model = new ContentItemHtml();
if (isset(Yii::$app->request->post()['ContentItemHtml'])) {
$item = Yii::$app->request->post()['ContentItemHtml'];
$model->contentitemgroupid = $contentitemgroupid;
$model->title = $item['title'];
$model->body = $item['body'];
$model->save();
// return $this->redirect(['edit', 'id' => $model->contentitemgroupid]);
}
else
return $this->renderPartial('_ContentItemHtml', ['model' => $model]);
}
Active form in view:
echo $form->field($model, 'body')->widget(CKEditor::className(), [
'preset' => 'custom',
'clientOptions' => [
'height' => 200,
'toolbarGroups' => [
['name' => 'basicstyles', 'groups' => ['basicstyles', 'cleanup']],
['name' => 'paragraph', 'groups' => ['templates', 'list']],
['name' => 'mode']]
]])->label(false);
Script.js
$('#addNewContentItem').on('click', function (e) {
e.preventDefault();
var url = 'create-' + $('#itemSelector').val().toLowerCase() + '?contentitemgroupid=' + $('#itemSelector').attr('contentitemgroupid');
$.ajax({
type: 'POST',
url: url,
cache: false,
success: function(res) {
$('.contentItemsManager').append('<div class="ContentItemContainer row">' + res + '</div>');
AddSaveEventListener();
AddSaveMediafileEventListener();
AddRemoveEventListener();
}
});
});
Use renderAjax instead of renderPartial. From the docs:
[renderAjax] Renders a view in response to an AJAX request.
This method is similar to renderPartial() except that it will inject into the rendering result with JS/CSS scripts and files which are registered with the view. For this reason, you should use this method instead of renderPartial() to render a view to respond to an AJAX request.
I'm going nuts with this. I am requesting ajax call in several places, and none of these ajax calls are working correctly lately. Today I decided to start fresh on a new section with ajax call. It's the same thing with all the other ones. It's been days that ajax data is not posting to controller - always blank.
Here is one of them. I am trying to allow users to vote up/down on click on CButtonColumn {up}{down}. This view grid "_vote.php" is generated through renderPartial using TbTabs. On renderpartial I did set to true on the last param.
Okay, next the grid. Here it is:
<?php $this->widget('bootstrap.widgets.TbGridView', array(
'type'=>'condensed',
'id'=>'vote',
'dataProvider'=>$dataProvider,
'template'=>"{items}",
'ajaxUpdate'=>true,
'columns'=>array(
array(
'class'=>'CButtonColumn',
'template' => '{up} {down}',
'buttons' => array(
'up' => array(
'label'=>'<i class="fa fa-thumbs-up"></i>',
'imageUrl'=>false,
'url'=>'Yii::app()->createUrl("prod/votecommentup", array("id"=>$data->primaryKey))',
'click'=>' function(){
$.fn.yiiGridView.update("vote", {
type:"POST",
url:$(this).attr("href"),
success:function(data) {
$.fn.yiiGridView.update(vote);
}
}',
),
'down'=> array(
'label'=>'<i class="fa fa-thumbs-down"></i>',
'imageUrl'=>false,
'url'=>'Yii::app()->createUrl("prod/votecommentdown", array("id"=>$data->primaryKey))',
'click'=>' function(){
$.fn.yiiGridView.update("vote", {
type:"POST",
url:$(this).attr("href"),
success:function(data) {
$.fn.yiiGridView.update(vote);
}
}',
),
),
),
),
)); ?>
Okay... next, the url "prod/votecommentup", which is the nearly identical as votecommentdown. Here it is:
public function actionVoteCommentUp($id){
$model = $this->loadModel($id);
if(isset($_POST['VoteThis']))
{
$model->attributes=$_POST['VoteThis'];
$model->prototype_review_id = $id;
$model->user_id = Yii::app()->user->user_id;
$model->vote = "Y";
echo CJSON::encode(array('status'=>'saved'));
}echo CJSON::encode(array('status'=>'not post')); //always give me a no post
}
I recommend testing your calls through something like Postman App for chrome. This will give you the ability to debug your API/AJAX calls independent of your view. Once you have ensured the API/AJAX is functioning correctly, you can then integrate it into the view. This allows you to decouple the debugging process and hopefully make things more transparent as to what is functional and what is not.
I run a "strip out" version of FB bigPipe and it's working perfect, except the jquery. When I parse the jquery in json format and append to a div tag, the jquery stop working.
You can see the "bigPipe" jquery code I use here
The code to get this working is pretty simple. In PHP:
$data = array(
'id' => {div tag ID},
'content' => {html content},
'title' => {document title},
'css' => {...},
'js' => {...}
);
$output = '<script>Test.render(' . json_encode($data) . ');</script>';
I think the problem is that I have to add window.addEventListener not to the window itself, but to the div tag I append the content.
And here I'm stuck. How do I do this? How do I get this jquery to work in this appended html?
Here is a example on how it should work:
If you try to run this code from a php file problems occur.Do this:
Put the js code from jsFiddle in a js file and include normaly in the .php file. Make a div tag in the php file and call it "not_working"- Save
Make a empty .html document and add a div tag like <div
id="test">Click me</div> and save.
Make a new js file and name it test.js.
Put in this code:
$(function() {
$("body").on("click","#test",function(){
alert("You clicked me!!");
});
});
Save.
In the PHP file, add this: $data = array(
'id' => "not_working",
'content' => {LINK and NAME to the HTML file you created!!},
'title' => "Test",
'css' => "",
'js' => {LINK and NAME to the JS file you created!!},
);
Run the .php file, click on the Click me!.
Problem solved. It was a error in the way the js files was inserted into the body element. After fixing that code. I solved it, and now everything work perfect.
If someone try to use this code, here is the changes:
function _addJsFile(filename) {
var blody = document.getElementsByTagName("body")[0],
script = document.createElement('script'),
done = false;
script.src = filename;
script.type='text/javascript';
script.onload = function() {
if (!done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
done = true;
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
if (blody && script.parentNode) {
blody.removeChild(script);
}
}
};
blody.appendChild(script);
}
I am working with Js helper to help me replace the contents of a "div" in my index.ctp with contents of another file changeto.ctp .
This application has a few check boxes with corresponding images. When I select a checkbox, the setting is stored in the database and the corresponding image is to be displayed. Similarly when unchecked, it is to be removed from the database and the image should disappear.
I am using the Js helper for this :
my changeto.ctp is subset of my index.ctp and has access to same variables and loads without any problems (except that any click/change events are just not responded to. The names of the Ids of the checkboxes are exactly same).
My index file contains the following Js code at the bottom of all Html:
$this->Js->get($change_checkbox1 )->event('click',
$this->Js->request(array(
'controller'=>'testing',
'action'=>'changeto'
), array(
'update'=>'#changeDiv',
'async' => true,
'method' => 'post',
'dataExpression'=>true,
'data'=> $this->Js->serializeForm(array(
'isForm' => false,
'inline' => true
))
))
);
This is generating the following Jquery/javascript
$(document).ready(function () {$("#ck0_1_8").bind("click", function (event) {$.ajax({async:true, data:$("#ck0_1_8").closest("form").serialize(), dataType:"html", success:function (data, textStatus) {$("#changeDiv").html(data);}, type:"post", url:"\/mytest-site\/options\/testing"});
return false;});
}
My controller has a function called
changeto()
{
$this->layout = 'ajax';
}
the first time I click on this the checkbox this works without any problem. However any subsequent clicks don't work. The javascript is not even being called.
My questions are :
Any ideas ?
Will it help if I somehow ask cakephp to use on() / live() insead of bind() .If yes how ?
Thanks!!
Solved this by editing a cakephp core file:
lib/Cake/View/Helper/JqueryEngineHelper.php
line 184:
change
return sprintf('%s.bind("%s", %s);', $this->selection, $type, $callback);
to
return sprintf('%s.live("%s", %s);', $this->selection, $type, $callback);
cake version 2.2.2
You have to use on instead of bind as they suggest in this question .live() vs .bind()
That's what I did was create my own Helper on View/Helper add the following method:
public function onEvent($selector, $type, $callback, $options = array()) {
$defaults = array('wrap' => true, 'stop' => true);
$options = array_merge($defaults, $options);
$function = 'function (event) {%s}';
if ($options['wrap'] && $options['stop']) {
$callback .= "\nreturn false;";
}
if ($options['wrap']) {
$callback = sprintf($function, $callback);
}
return sprintf('$(document).on("%s", "%s", %s);', $type, $selector, $callback);
}
And use that method from my views:
echo $this->MyJs->onEvent('#creditcards', 'change', $eventCode, array('stop' => false));
I was trying to convert this into a Drupal module so that I can check PHP code instantly on my site for debugging purposes. I saw this Firefox add on which allows you to execute PHP on the fly but admin log in is necessary, so far I did everything , have one form and set up ajax calls , but if I pass a string like:
preg_match($pat,$str,$matches);
print_r($matches);
How to execute this in backend?
EDIT
To load the form:
$items['localphp'] = array(
'page callback' => 'executePHP',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
function executePHP(){
$output = drupal_get_form('executePHP_form');
return $output;
}
Ajax callback function:
$items['runPHP'] = array(
'page callback' => 'getResult',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
function getResult(){
$code = $_POST['code'];
//I need help here how to execute $code i.e the php code and return back result
echo $code;
}
JS function
function executePHP(baseurl){
var code = $("#edit-code").val();
$.ajax({
type : "POST",
url : baseurl+'runPHP',
data : 'code='+code,
async : true,
cache : false,
success : function (res) {
$("#edit-result").html(res);
},
error : function (res) {
alert("error");
}
});
return false;
}
FYI, the Devel module has a feature that allows admins to run custom PHP code from their page. The Devel module has a block with a ton of features useful for debugging.
For a custom module, without seeing any of your other code, I can tell you what I have done to achieve AJAX in a Drupal module:
In JavaScript make an AJAX request to a url on your site. Add a menu item with the specified path inside of hook_menu() as 'type' => MENU_CALLBACK that points to a function in your module. This function should do all the processing you need, then return the results to JavaScript to do what you want with it there.