How to define custom class, title, and target in Link Browser for content elements and the new rte_ckeditor? - typo3

Prerequisites
[x] Can you reproduce the problem on TYPO3 8.7 LTS - YES
[x] Did you [perform a cursory search] to see if your bug or enhancement is already reported? -YES
Description
How do I configure default link target, class, and title for the Link Browser in any element link (usually element titles and images) AND in rte_ckeditor in Typo3 8 LTS? I've spent several hours trying to configure it, but no success and no documentation out there. The fields are empty as you can see on the images below.
Steps to Reproduce the problem
Create any element that you can link the title or image.
Click to open the Link Browser
The options come empty for any type of link (Page, File, Folder, External URL, Email).
Expected behavior:
I want to define default classes, link targets and titles for each type of link if they are empty.
For example External URL, I want to automatically populate with target="_blank", class "external-link", title="Link to External Website", if the link wasn't configure previously. Basically for any new link I just want to have it auto populated with my custom values and not empty values.
This used to work for rtehtmlarea only on previous Typo3 versions, but not I'm not able to set this option system wide on Typo3 8 LTS and ckeditor.
The PageTS that used to work only for rtehtmlarea was something like this:
RTE {
classesAnchor {
externalLink {
class = external-link
type = url
titleText = Opens external link in new window
target = _blank
image =
}
externalLinkInNewWindow {
class = external-link-new-window
type = url
titleText = Opens external link in new window
target = _blank
image =
}
internalLink {
class = internal-link
type = page
titleText = Opens internal link in this window
target = _top
image =
}
internalLinkInNewWindow {
class = internal-link-new-window
type = page
titleText = Opens internal link in new window
target = _blank
image =
}
folder {
class = folder
type = folder
titleText =
target =
image =
}
download {
class = download
type = file
titleText = Initiates file download
target = _blank
image =
}
mail {
class = mail
type = mail
titleText = Email Address
image =
}
}
}
I would like this to work for the new rte_ckeditor as well for any element options that I can link using the Link Browser.

There is a bug in TYPO3 8.7.8 (only) - see: https://forge.typo3.org/issues/82865
[EDIT] the classesAnchor stuff works only in version 8.7.5 to 8.7.7 and will hopefully work again in 8.7.9
But the correct answer whould be (like Ghanshyam Bhava pointed out in his comment) to switch to YAML configuration.
https://typo3worx.eu/2017/02/configure-ckeditor-in-typo3/
# Load default processing options
imports:
- { resource: "EXT:rte_ckeditor/Configuration/RTE/Default.yaml" }
classesAnchor:
externalLink:
class: 'external-link'
type: 'url'
downloadLink:
class: 'download-link'
type: 'file'
mailLink:
class: 'mail-link'
type: 'mail'
buttons:
link:
properties:
class:
allowedClasses: 'external-link,download-link,mail-link'
Link Browsers for other fields outside RTE should be possible via TCA-Overrides.

Here is the solution,
RTE.default {
# This will provide only basic tool in the text RTE
preset = default
## Bootstrap CSS
contentCSS {
20 = fileadmin/Resources/Public/Bootstrap/css/bootstrap.css
}
classesAnchor {
url {
class = externalLink
type = url
titleText = Opens external link in new window
target = _blank
image =
}
page {
class = internalLink
type = page
titleText = Opens internal link in this window
target = _top
image =
}
file {
class = download
type = file
titleText = external file
target = _blank
image =
}
folder {
class = folder
type = folder
titleText = folder file
target = _blank
image =
}
mail {
class = mail
type = mail
titleText = Email Address
image =
}
}
buttons.link{
page.properties.class.default = internalLink
url.properties.class.default = externalLink
folder.properties.class.default = folder
file.properties.class.default = download
mail.properties.class.default = mail
properties.class.allowedClasses = internalLink,externalLink,folder,mail,download
}
}
Check out this, i have added default link title as well as its targer too. you can see the output of my backend:

So after days and days and days!!! of search, trials, and errors, I finally found a way to enable the auto populated parameter of a link according to their type outside rte_ckeditor or even outside rtehtmlarea. It's not exactly what I wanted but is almost there!
Adding this to my Page TSConfig solved part of the problem:
TCEMAIN.linkHandler {
# I don't want to load the folder link handler so I reset it.
folder >
# Leaving page type empty on purpose.
page {
}
file {
addParams = onclick="jumpToUrl('?act=file&linkAttributes[target]=_blank&linkAttributes[title]=Opens or downloads file in new window&linkAttributes[class]=download&linkAttributes[params]=');return false;"
}
url {
addParams = onclick="jumpToUrl('?act=url&linkAttributes[target]=_blank&linkAttributes[title]=Opens external link in new window&linkAttributes[class]=externalLink&linkAttributes[params]=');return false;"
}
mail {
addParams = onclick="jumpToUrl('?act=mail&linkAttributes[title]=Opens email manager to send an email&linkAttributes[class]=mail&linkAttributes[params]=');return false;"
}
}
I didn't configure anything for page because if it's populated and I click on File, External Url, Email, or any other custom link handler, the attributes are passed along from the Page link handler, which defeats the purpose of the pre-populated parameters for each link handler type.
The only remaining issue is if I click for example on External URL, the target will be "_blank", title will be "Opens external link in new window" and class will be "externalLink". So far so good. Then if you click to link a File or even to link an internal Page, those parameters that pre-loaded for External URL will be passed along, which I think it shouldn't happen. Since I'm trying to pre-populate each link type, why would I want to keep the attribute of a previous link type? This might be just a matter of opinion, but I would like to have the option for force pre-populated parameters for each link type. Maybe I'm just missing a small config to achieve this behavior.

I have tested this solution in TYPO3 9 with ckeditor in my yaml configuration file to load my own defaults. It works fine except the default settings don't work as expected. The titleText, is currently overwritten by the last title of the same type. e.g. for the type 'page' the title 'Opens internal link in new window' is loaded instead of 'Opens internal link in this window'.
buttons:
link:
relAttribute:
enabled: true
page:
properties:
class:
default: internal-link
url:
properties:
class:
default: external-link-new-window
folder:
properties:
class:
default: folder
file:
properties:
class:
default: download
mail:
properties:
class:
default: mail
properties:
class:
allowedClasses: 'internal-link,internal-link-new-window,download,external-link,external-link-new-window,mail'
#Classes config
classesAnchor:
internalLink:
class: 'internal-link'
type: 'page'
titleText: 'Opens internal link in this window'
internalLinkNewWindow:
class: 'internal-link-new-window'
type: 'page'
target: '_blank'
titleText: 'Opens internal link in new window'
download:
class: 'download'
type: 'file'
target: '_blank'
titleText: 'Download file'
externalLink:
class: 'external-link'
type: 'url'
titleText: 'Opens External link in this window'
externalLinkNewWindow:
class: 'external-link-new-window'
type: 'url'
target: '_blank'
titleText: 'Opens External link in new window'
linkMail:
class: 'mail'
type: 'mail'
titleText: 'Email Address'

To configure default classes in yaml you have to add the default classes like this in your .yaml file:
classesAnchor:
page:
class: 'link-page'
type: 'page'
target: '_top'
file:
class: 'link-file'
type: 'file'
target: '_blank'
titleText: 'Download'
url:
class: 'link-external'
type: 'url'
target: '_blank'
mail:
class: 'link-mail'
type: 'mail'
titleText: 'Send email'
buttons:
link:
properties:
class:
allowedClasses: 'link-page, link-file, link-external, link-mail'
page:
properties:
class:
default: 'link-page'
file:
properties:
class:
default: 'link-file'
url:
properties:
class:
default: 'link-external'
mail:
properties:
class:
default: 'link-mail'

Related

VSCode Extension: How to open a file if no workspace folders are available?

I've been working on an extension that allows adding files with pre-defined content and modifying them using a custom web editor.
The custom command "Add new XXX file" looks like the following:
let disposable = vscode.commands.registerCommand('myextension.add-new-file', () => {
if(vscode.workspace.workspaceFolders?.length){
const rootPath = vscode.workspace.workspaceFolders[0].uri.fsPath ;
let counter = 0;
let filePath = '';
do{
counter++;
filePath = path.join(rootPath, `NewFile${counter}.my-ext`);
}while(fs.existsSync(filePath));
fs.writeFileSync(filePath, JSON.stringify(newFileContent), 'utf8');
const openPath = vscode.Uri.file(filePath);
vscode.commands.executeCommand('vscode.openWith', openPath, 'myextension.custom-designer');
}
});
It works OK if a folder is opened in VS Code. However, if no folder is opened, the rootPath can't be resolved. What's the solution for such a scenario? Does the 'vscode.openWith' accept the file content instead of the path to open?
You can accomplish your goal using the untitled scheme:
vscode.commands.executeCommand(
'vscode.openWith',
vscode.Uri.parse("untitled:FooBar"),
'myextension.custom-designer',
);
You can change your custom editor so that it detects when empty document gets passed to it and replaces the empty document with newFileContent.

Upload Images and files with TinyMCE

In my symfony2 project I use TidyMCE in my textareas, to be able to insert news from the backend. News can have images in the content or files links to pdf files to display. I am new to this and I can not upload the images or files, so that I can search the different folders and once selected a copy is made on the server.
I've been looking at a lot of comments, but I'm kind of bundled up. I have seen on the web of tinymceel following code:
Basic Local File Picker
tinymce.init({
selector: '#editor',
plugins: 'image code',
toolbar: 'undo redo | link image | code',
// enable title field in the Image dialog
image_title: true,
// enable automatic uploads of images represented by blob or data URIs
automatic_uploads: true,
// URL of our upload handler (for more details check: https://www.tinymce.com/docs/configure/file-image-upload/#images_upload_url)
images_upload_url: 'postAcceptor.php',
// here we add custom filepicker only to Image dialog
file_picker_types: 'image',
// and here's our custom image picker
file_picker_callback: function(cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
// Note: In modern browsers input[type="file"] is functional without
// even adding it to the DOM, but that might not be the case in some older
// or quirky browsers like IE, so you might want to add it to the DOM
// just in case, and visually hide it. And do not forget do remove it
// once you do not need it anymore.
input.onchange = function() {
var file = this.files[0];
// Note: Now we need to register the blob in TinyMCEs image blob
// registry. In the next release this part hopefully won't be
// necessary, as we are looking to handle it internally.
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var blobInfo = blobCache.create(id, file);
blobCache.add(blobInfo);
// call the callback and populate the Title field with the file name
cb(blobInfo.blobUri(), { title: file.name });
};
input.click();
}
});
PHP Upload Handler
<?php
/*******************************************************
* Only these origins will be allowed to upload images *
******************************************************/
$accepted_origins = array("http://localhost", "http://192.168.1.1", "http://example.com");
/*********************************************
* Change this line to set the upload folder *
*********************************************/
$imageFolder = "images/";
reset ($_FILES);
$temp = current($_FILES);
if (is_uploaded_file($temp['tmp_name'])){
if (isset($_SERVER['HTTP_ORIGIN'])) {
// same-origin requests won't set an origin. If the origin is set, it must be valid.
if (in_array($_SERVER['HTTP_ORIGIN'], $accepted_origins)) {
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
} else {
header("HTTP/1.0 403 Origin Denied");
return;
}
}
/*
If your script needs to receive cookies, set images_upload_credentials : true in
the configuration and enable the following two headers.
*/
// header('Access-Control-Allow-Credentials: true');
// header('P3P: CP="There is no P3P policy."');
// Sanitize input
if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) {
header("HTTP/1.0 500 Invalid file name.");
return;
}
// Verify extension
if (!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) {
header("HTTP/1.0 500 Invalid extension.");
return;
}
// Accept upload if there was no origin, or if it is an accepted origin
$filetowrite = $imageFolder . $temp['name'];
move_uploaded_file($temp['tmp_name'], $filetowrite);
// Respond to the successful upload with JSON.
// Use a location key to specify the path to the saved image resource.
// { location : '/your/uploaded/image/file'}
echo json_encode(array('location' => $filetowrite));
} else {
// Notify editor that the upload failed
header("HTTP/1.0 500 Server Error");
}
?>
But I do not quite understand where to put the postAcceptor.php or referred to with {location: '/ your / uploaded / image / file'}.
I'm a little lost, please thank all the possible help
postacceptor is your server side method for accepting the file and uploading it in your server. I am using mvc so I created a custom route "ImageUpload". and I use that instead.
location part is the expected return from your method. this will replace the file location/referrer a.k.a src tag when you use images_reuse_filename = true.
I don't use symphony but according to your code you would put the postAcceptor file in the same directory as form

Tinymce 4 file_browser_callback: Function for opening a local file browser

I use Tinymce 4.0 on my web application. But I really don't know how to do this: when the user click on the browse button, how to open a local file browser and add an image URL to the dialog window from this local file browser? I have this source code:
file_browser_callback: function(field_name, url, type, win) {win.document.getElementById(field_name).value = ''; }
But I don' t know how to solve this problem. I don't need a special file browser but function for opening local file browser.
Here the snippet from Basic Local File Picker demo from TinyMCE docs:
Note: Unfortunately it doesn't seem to work here as a StackOverflow snippet.
tinymce.init({
selector: '#editor',
plugins: 'image code',
toolbar: 'undo redo | link image | code',
// enable title field in the Image dialog
image_title: true,
// enable automatic uploads of images represented by blob or data URIs
automatic_uploads: true,
// URL of our upload handler (for more details check: https://www.tinymce.com/docs/configure/file-image-upload/#images_upload_url)
images_upload_url: 'postAcceptor.php',
// here we add custom filepicker only to Image dialog
file_picker_types: 'image',
// and here's our custom image picker
file_picker_callback: function(cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
// Note: In modern browsers input[type="file"] is functional without
// even adding it to the DOM, but that might not be the case in some older
// or quirky browsers like IE, so you might want to add it to the DOM
// just in case, and visually hide it. And do not forget do remove it
// once you do not need it anymore.
input.onchange = function() {
var file = this.files[0];
// Note: Now we need to register the blob in TinyMCEs image blob
// registry. In the next release this part hopefully won't be
// necessary, as we are looking to handle it internally.
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var blobInfo = blobCache.create(id, file);
blobCache.add(blobInfo);
// call the callback and populate the Title field with the file name
cb(blobInfo.blobUri(), { title: file.name });
};
input.click();
}
});
<script src="//cdn.tinymce.com/4/tinymce.js"></script>
<textarea id="editor"></textarea>

Create a new link stye in Typo3?

Is there a way to add a new style to the Insert Link dialog in Typo3?
Currently they are "internal-link", "internal-link-new-window", or no style.
I have tried putting various things in the Page tsconfig with no results at all...
I found this on another site which looks like it does what I want but I can't get it to do anything:
RTE.classesAnchor {
tollerLink1 {
class = button
type = page
titleText = Button
}
}
RTE.default {
classesAnchor:=addToList(button)
}
In your TsConfig (Home Page Properties - Resources - Page TSConfig)
RTE.default.buttons {
link.properties.class.allowedClasses := addToList(internal-link-new-window)
}

Display external link in popup in Liferay

Am using Liferay 6.2 and trying to get a external page in a pop up.
Am using the following code
function ShowPopup(){
AUI().ready(function(A) {
AUI().use('aui-dialog', 'aui-io', function(A) {
var url1 = '/myportlet/myview.jsp';
// var url1 = 'www.google.com';
Liferay.Util.openWindow(
{
dialog: {
cache: false,
width: 800,
height: 700,
modal: true
},
id:'myview',
uri: url1
}
);
Liferay.provide(
window,
'closePopup',
function(popupIdToClose) {
var dialog = Liferay.Util.getWindow(popupIdToClose);
dialog.destroy(); // You can try toggle/hide whatever You want
},
['aui-base','aui-dialog','aui-dialog-iframe']
);
});
});
If I provide the first var url1('/myportlet/myview.jsp'), the popup displays properly, as it is internal link, But if I provide the second var url1('www.google.com'). The localhost url is prepended for the URI(like http://localhost:8080/www.google.com), so it is not able to display the external link in pop up.
How can i make the external url display in the popup.
If your target has different domain, you should use absolute URL including protocol - http://www.google.com.
Anyway, I think it may be hard to embed google as recently there is new trend for securing sites against iframing (and I think google has introduced these improvements). More details here How to show google.com in an iframe?.