allowed cTypes in backenlayouts / gridelements not working anymore in TYPO3 7.6? - typo3-7.6.x

TYPO3 7.6.4
I have several backendlayouts and also one gridelement for 2col.
Now I limit the available cTypes for each column like this:
(just an example)
mod {
web_layout {
BackendLayouts {
Home {
title = Home
config {
backend_layout {
colCount = 1
rowCount = 3
rows {
1 {
columns {
1 {
name = Slider
colPos = 1
colspan = 1
allowed = custom_slider
}
}
}
2 {
columns {
1 {
name = Content
colPos = 0
colspan = 1
allowed = header, html, shortcut
}
}
}
}
}
}
icon = icon/path
}
...
For the columns slider it works just fine.
FOr column content the NewContentWizard shows this 3 Elements, but when I add one, the only element that is allowed (listed in the cType dropdown) is "header" - in that case - so in general its the first cType from allowed.
Does anyone can reproduce or now what's the problem? Otherwise it could be a bug and I'll report it.
Thanks for any feedback or solution!
Kind regards
Tobi

Here's a compact way to manage the "New Content Element Wizard" via the core / Page TSConfig:
// remove everything
mod.wizards.newContentElement.wizardItems.common.show =
mod.wizards.newContentElement.wizardItems.special.show =
mod.wizards.newContentElement.wizardItems.forms.show =
mod.wizards.newContentElement.wizardItems.plugins.show =
// add additional tabs like mask if available
// add specific - by colPos and backend_layout (if needed)
[globalVar = GP:colPos==0]&&[page|backend_layout = 0]
mod.wizards.newContentElement.wizardItems.common.show := addToList(header)
[end]

The problem was that I put whitespaces into the list...
so changing
allowed = header, html, shortcut
into
allowed = header,html,shortcut
works like expacted.

You could also use this code, which only keeps the selected items. This also removes plugins and items in other tabs
[globalVar = GP:colPos==0]&&[page|backend_layout = 0]
TCEFORM.tt_content.CType.keepItems := addToList(header)
[end]

Related

GAS: copy one data validation (dropdown) in N number of rows and set unique value in each dropdown

Edited for clarity and to add images
Using Google Apps Script, how can I:
copy a range from Section 2 sheet (G11:H11, with a checkbox & dropdown) into range G12:G25 N number of times (based on the number of non-empty rows in MASTER DROPDOWN sheet under same header title as 'Section 2'!A2) and then,
set a different value in each dropdown (each unique value listed in MASTER DROPDOWN sheet under the correct header).
For example, first image is "MASTER DROPDOWN" sheet.
This second image is "Section 2" sheet. The user can add or delete items on the list using the buttons on the right side of the page.
And this last image is "Section 2" sheet. I cannot understand how to write the code for this... When user presses "Reset list" button, I want to copy checkbox and dropdown menu (from G11:H11) N number of times (N=3 based on number of items from MASTER DROPDOWN under Section 2). In each dropdown, I want to set value with each item from the original list in the MASTER DROPDOWN sheet. This process should be dynamic and work on Section 1 and Section 3 sheet (not in worksheet currently).
Any advice on the script verbage to search/learn about this type of functionality, or some direction on the script for this is much appreciated. Here's a link to my code that I have so far...
https://docs.google.com/spreadsheets/d/1ZdlJdhA0ZJOIwLA9dw5-y5v1FyLfRSywjmQ543EwMFQ/edit?usp=sharing
function newListAlert (){
var ui = SpreadsheetApp.getUi();
var response = ui.alert("Are you sure you want to delete your current list and create a new one?",ui.ButtonSet.YES_NO);
if(response == ui.Button.YES) {
newList();
} else {
}
}
function newList() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = ss.getRange("G11:H25");
var options = {contentsOnly: true, validationsOnly: true};
//clear current list
range.clear(options);
//add new item to list in first row of range
addNewItem();
//copy new datavalidation row above based on number of non-empty rows in MASTER DROPDOWN with same header as active sheet (-1)
var datass = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MASTER DROPDOWN");
var range = ss.getRange("A2");
if (range.getCell(1,1)){
var section = datass.getRange(1,1,1,datass.getLastColumn()).getValues();
var sectionIndex = section[0].indexOf(range.getValue()) + 1;
var validationRange = datass.getRange(4,sectionIndex,19);//19 columns: checklist has a maximum of 18 rows (+ 1 for "select option")
}
}
In your situation, how about modifying newList() as follows?
Modified script:
function newList() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getSheetName();
sheet.getRange("G11:H25").clear({ contentsOnly: true, validationsOnly: true });
var srcSheet = ss.getSheetByName("MASTER DROPDOWN");
var values = srcSheet.getDataRange().getValues();
var obj = values[0].map((_, c) => values.map(r => r[c])).reduce((o, [h, , , ...v], i) => {
if (h != "") {
v = v.filter(String);
v.shift();
o[h] = { values: v, range: srcSheet.getRange(4, i + 1, v.length + 1) };
}
return o;
}, {});
if (obj[sheetName]) {
var validationRule = SpreadsheetApp.newDataValidation()
.setAllowInvalid(false)
.setHelpText('Select an option from the menu. To add more options to the dropdown list, go to MASTER DROPDOWN tab.')
.requireValueInRange(obj[sheetName].range, true)
.build();
var d = obj[sheetName].values.map(_ => [validationRule]);
var v = obj[sheetName].values.map(e => [e]);
sheet.getRange(sheet.getLastRow() + 1, 8, obj[sheetName].values.length).setDataValidations(d).setValues(v).offset(0, -1).insertCheckboxes();
}
}
When this script is run, the values for DataValidations are retrieved from the sheet "MASTER DROPDOWN", and using the sheet name, the dataValidation rules are created, and put to the column "H". And also, the checkboxes are put to the column "G" of the same rows of the dataValidations.
In this case, for example, when you add a new sheet of "Section 1" and run newList(), the dropdown list including "Engineering" and "Design" is put to the column "H" and the checkboxes are also put to the column "G".
Note:
In this modification, the sheet name like "Section 2" is used for searching the column of "MASTER DROPDOWN" sheet. So please be careful about this.
And, from your current script, the last row is used for putting to the dropdown list and checkboxes. So when you want to modify this, please modify the above script.
This sample script is for your sample Spreadsheet. So when your actual Spreadsheet is changed, this script might not be able to be used. Please be careful this.
References:
setDataValidations(rules)
insertCheckboxes()

How can I make Xcode not auto indent Eureka forms code in a weird way?

When I use Eureka forms, Xcode seems to like to format it in a way that could cause confusion.
I'll use the one of the code blocks in the README as an example:
let row = SwitchRow("SwitchRow") { row in // initializer
row.title = "The title"
}.onChange { row in
row.title = (row.value ?? false) ? "The title expands when on" : "The title"
row.updateCell()
}.cellSetup { cell, row in
cell.backgroundColor = .lightGray
}.cellUpdate { cell, row in
cell.textLabel?.font = .italicSystemFont(ofSize: 18.0)
}
This really makes my OCD go off. The last } isn't inline with all the other ones feels so annoying.
I would like to format it like so:
let row = SwitchRow("SwitchRow") { row in // initializer
row.title = "The title"
}.onChange { row in
row.title = (row.value ?? false) ? "The title expands when on" : "The title"
row.updateCell()
}.cellSetup { cell, row in
cell.backgroundColor = .lightGray
}.cellUpdate { cell, row in
cell.textLabel?.font = .italicSystemFont(ofSize: 18.0)
}
Or this:
let row = SwitchRow("SwitchRow") { row in // initializer
row.title = "The title"
}.onChange { row in
row.title = (row.value ?? false) ? "The title expands when on" : "The title"
row.updateCell()
}.cellSetup { cell, row in
cell.backgroundColor = .lightGray
}.cellUpdate { cell, row in
cell.textLabel?.font = .italicSystemFont(ofSize: 18.0)
}
So I went to the preference pane of Xcode and looked for things like custom indentation. I thought there would be something similar to the formatting settings in IntelliJ, but I found nothing.
Then I found the closest thing to what I'm looking for - Automatic Indent. So I unchecked the checkbox for }, like the:
But as I type .onChange { then press enter, this happens:
let row = SwitchRow("") {
row in
}.onChange {
}
How can make it not automatically indent to that? I want one of the styles mentioned above.
If you are willing to use the non-trailing syntax, i.e. with extra parentheses (which admittedly bloat the code a bit) the auto-indentation should work fine.
Your example code gets formatted to:
let row = SwitchRow("SwitchRow", { row in // initializer
row.title = "The title"
}).onChange({ row in
row.title = (row.value ?? false) ? "The title expands when on" : "The title"
row.updateCell()
}).cellSetup({ cell, row in
cell.backgroundColor = .lightGray
}).cellUpdate({ cell, row in
cell.textLabel?.font = .italicSystemFont(ofSize: 18.0)
})
Though this does not prevent Xcode from formatting it every time, I think this suffices in most cases.
The solution is to uncheck auto indentation for {:
Apparently what those checkboxes control is "whether to auto indent when these keys are pressed".
If the { box is checked, Xcode will auto indent the current line when I type {, moving the whole }.onChange{ line to the right. If it is unchecked, this will not happen.

jQuery Isotope 2.1 Pagination

I'm trying to paginate items using jQuery Isotope 2.1. I have a set of items which can be filtered. I'd like to be able to limit the displayed items using a range. If I want to display 10 items per page, I'd tell it show all items between 11 and 20 in the filtered set for page 2, for example.
To make matters more complex, items can be sorted as well.
Is there any way to do this?
I thought about toggling a "active" class on the filtered items, then using JS and CSS I would only show items with the "active" class that are within the current range. Not sure if that's the most efficient approach.
Thanks,
Howie
I was able to solve the problem by prototyping the _filter method.
Firstly, I call the _sort method before attempting to filter the items since sorting will affect which items are displayed on each page.
Then I added a few parameters to the options object, such as page and items_per_page. Using these two values, I can calculate the first and last item for the intended page. Even though it's not necessary for pagination, I also added a parameter called activeClass which defaults to active and is added to all matching items. In addition I added and odd-item and an even-item class to each item so that in a list view, for example, I can alternate the row colors.
Lastly, I set a property on the this object called all_matches to the entire set of filtered items. This way I can calculate the total number of pages for my pager. Then I return only the filtered items for the current page.
On the layoutComplete event, I use the page and items_per_page values from the options object in order to calculate the first and last item and update my pager.
I happen to be using Bootstrap along with a customized version of the Bootpag pager which accepts itemsPerPage and totalItems.
You can check out the codepen here. Hope it helps.
Isotope.prototype._filter = function (items)
{
//console.log('FILTER ' + arguments.callee.caller.toString());
var filter = this.options.filter;
filter = filter || '*';
var matches = [];
var all_matches = [];
var hiddenMatched = [];
var visibleUnmatched = [];
var start, end;
//console.log('page: ' + this.options.page + ' items per page: ' +
this.options.items_per_page);
start = (this.options.page - 1) * this.options.items_per_page;
end = this.options.page * this.options.items_per_page;
//console.log('start: ' + start + ' end: ' + end + ' page: ' +
this.options.page);
// we want to set the current value of filteredItems to all items
before we sort
// we must sort first becuase we need to make sure we are showing
// the correct results for each page in the correct order
this.filteredItems = items;
this._sort();
if (this.options.activeClass === undefined ||this.options.activeClass === '')
{
this.options.activeClass = 'active';
}
var test = this._getFilterTest(filter);
// test each item
for (var i = 0, len = items.length; i < len; i++)
{
//console.log('item: ' + i, $(items[i].element).find('.grid-item-title .asset-link').text(), items[i]);
var item = items[i];
if (item.isIgnored)
{
continue;
}
// add item to either matched or unmatched group
var isMatched = test(item);
// add to matches if its a match
if (isMatched)
{
all_matches.push(item);
// before we add it to the matched set, let's make sure if falls within range
// it needs to be part of the current page set otherwise we filter it out
if (all_matches.length > start && all_matches.length <= end)
{
matches.push(item);
var odd_even = (matches.length % 2 === 0) ? 'even-item' : 'odd-item';
$(item.element).addClass(this.options.activeClass + ' ' + odd_even);
} else
{
// we need to reset isMatched if we're not using it on the current page
isMatched = false;
$(item.element).removeClass(this.options.activeClass + ' odd-item even-item');
}
}
// add to additional group if item needs to be hidden or revealed
if (isMatched && item.isHidden)
{
// reveal these items
hiddenMatched.push(item);
} else if (!isMatched && !item.isHidden)
{
// hide these items
visibleUnmatched.push(item);
}
}
var _this = this;
function hideReveal()
{
_this.reveal(hiddenMatched);
_this.hide(visibleUnmatched);
}
if (this._isInstant)
{
this._noTransition(hideReveal);
} else {
hideReveal();
}
// set all matches as a property on 'this' since we'll need it later to build the pager
this.all_matches = all_matches;
return matches;
};
H

Select hyphenated word with double-click

UPDATE: Per the recommendation below, here's specifically what I'd like to do: If I double-click the mouse cursor anywhere from the "b" to the "n" of "blue-green", I want all of the word "blue-green" should be highlighted. How can this be done? Currently, depending on where you click, it treats "blue-green" as three separate character strings. So, if you double click between the "b" and "e" of "blue" it highlights only "blue" and not "-green." If you double-click the hyphen, it highlights the hyphen alone. And if you double-click between the "g" and "n" of "green" it highlights only "green" and not "blue-".
ORIGINAL: When I double-click a hyphenated word or set of characters (e.g. "123-abc" or "blue-green" etc.), only the part of the word that I double-clicked is highlighted. I'd like the whole word to be highlighted.
I'm using Windows 7 Pro. If it needs to be done on a per-application basis, I'm most interested in fixing it for Google Chrome, but any Windows-compatible web browser would be OK.
Old question, but I happen to have been working on the same issue. Here's my solution:
jsFiddle.net
"use strict"
// Tweak to make a double-click select words with hyphens
//
// As of 2016-0816, None of the major Mac browser selects whole words
// with hyphens, like "ad-lib". This tweak fixes the hypen issue.
//
// Note: Firefox 48.0 doesn't automatically select whole words with
// apostrophes like "doesn't". This tweak also treats that.
;(function selectWholeWordsWithHyphens(){
var pOutput = document.getElementById("output")
var selection = window.getSelection()
// Regex designed to find a word+hyphen before the selected word.
// Example: ad-|lib|
// It finds the last chunk with no non-word characters (except for
// ' and -) before the first selected character.
var startRegex = /(\w+'?-?)+-$/g
// Regex designed to find a hyphen+word after the selected word.
// Example: |ad|-lib
var endRegex = /^-('?-?\w+)+/
// Edge case: check if the selection contains no word
// characters. If so, then don't do anything to extend it.
var edgeRegex = /\w/
document.body.ondblclick = selectHyphenatedWords
function selectHyphenatedWords(event) {
if (!selection.rangeCount) {
return
}
var range = selection.getRangeAt(0)
var container = range.startContainer
var string = container.textContent
var selectionUpdated = false
if (string.substring(range.startOffset, range.endOffset)
.search(edgeRegex) < 0) {
// There are no word characters selected
return
}
extendSelectionBackBeforeHypen(string, range.startOffset)
extendSelectionForwardAfterHyphen(string, range.endOffset)
if (selectionUpdated) {
selection.removeAllRanges()
selection.addRange(range)
}
function extendSelectionBackBeforeHypen(string, offset) {
var lastIndex = 0
var result
, index
string = string.substring(0, offset)
while (result = startRegex.exec(string)) {
index = result.index
lastIndex = startRegex.lastIndex
}
if (lastIndex === offset) {
range.setStart(container, index)
selectionUpdated = true
}
}
function extendSelectionForwardAfterHyphen(string, offset) {
if (!offset) {
return
}
string = string.substring(offset)
var result = endRegex.exec(string)
if (result) {
range.setEnd(container, offset + result[0].length)
selectionUpdated = true
}
}
}
})()
It's a standard through all programs that it will do that because they all run off the operating system's typing configuration/program thing. To fix it you would need to do something in System32. I don't know what you would need to do but I suspect this is your problem. You should probably go into more detail though about specifically what it is you want.

How to set cursor position to end of text in CKEditor?

Is there a way to set the cursor to be at the end of the contents of a CKEditor?
This developer asked too, but received no answers:
http://cksource.com/forums/viewtopic.php?f=11&t=19877&hilit=cursor+end
I would like to set the focus at the end of the text inside a CKEditor. When I use:
ckEditor.focus();
It takes me to the beginning of the text already inside the CKEditor.
Dan's answer got strange results for me, but minor change (in addition to typo fix) made it work:
var range = me.editor.createRange();
range.moveToElementEditEnd( range.root );
me.editor.getSelection().selectRanges( [ range ] );
According to the documentation for CKEditor 4, you can do the following once you have the editor object.
var range = editor.createRange();
range.moveToPosition( range.root, CKEDITOR.POSITION_BEFORE_END );
editor.getSelection().selectRanges( [ range ] );
Link: http://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection (under selectRanges function).
After a bit of fiddling, I've got it to work with the following code:
$(document).ready(function() {
CKEDITOR.on('instanceReady', function(ev) {
ev.editor.focus();
var s = ev.editor.getSelection(); // getting selection
var selected_ranges = s.getRanges(); // getting ranges
var node = selected_ranges[0].startContainer; // selecting the starting node
var parents = node.getParents(true);
node = parents[parents.length - 2].getFirst();
while (true) {
var x = node.getNext();
if (x == null) {
break;
}
node = x;
}
s.selectElement(node);
selected_ranges = s.getRanges();
selected_ranges[0].collapse(false); // false collapses the range to the end of the selected node, true before the node.
s.selectRanges(selected_ranges); // putting the current selection there
}
});
The idea is:
Get the root node (not body)
Advance to next node, until there are no more nodes to advance to.
Select last node.
Collapse it
Set range
Here's a similar answer to #peter-tracey. In my case my plugin is inserting a citation. If the user has made a selection, I needed to disable the selection and place the cursor at the end of the sentence.
// Obtain the current selection & range
var selection = editor.getSelection();
var ranges = selection.getRanges();
var range = ranges[0];
// Create a new range from the editor object
var newRange = editor.createRange();
// assign the newRange to move to the end of the current selection
// using the range.endContainer element.
var moveToEnd = true;
newRange.moveToElementEditablePosition(range.endContainer, moveToEnd);
// change selection
var newRanges = [newRange];
selection.selectRanges(newRanges);
// now I can insert html without erasing the previously selected text.
editor.insertHtml("<span>Hello World!</span>");
CKEditor 3.x:
on : {
'instanceReady': function(ev) {
ev.editor.focus();
var range = new CKEDITOR.dom.range( ev.editor.document );
range.collapse(false);
range.selectNodeContents( ev.editor.document.getBody() );
range.collapse(false);
ev.editor.getSelection().selectRanges( [ range ] );
}
}
based on pseudo-code provided by the developers here:
https://dev.ckeditor.com/ticket/9546#comment:3
You have to focus editor, get document object, put it in range,
collapse range (with false parameter), select body (with
selectNodeContents), collapse it (with false parameter) and finally
select range. It is best to do it all in instanceReady event.
This is the easiest solution provided by the ckeditor API. I have tested it on IE10+, ff, safari and Chrome:
range = editor.createRange();
// the first parameter is the last line text element of the ckeditor instance
range.moveToPosition(new CKEDITOR.dom.node(editor.element.$.children[pos - 1]), CKEDITOR.POSITION_BEFORE_END)
range.collapse()
editor.getSelection().selectRanges([ range ])
This will work for sure.
CKEDITOR.config.startupFocus = 'end';
have you tried ckEditor.Selection.Collapse(false);
According to CKEditor 4 documentation, another option is:
const range = this.ckeditor.createRange()
range.moveToElementEditablePosition(range.root, true)
this.ckeditor.getSelection().selectRanges([range])
Link: https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-moveToElementEditablePosition

Resources