stylescombo plugins with multiple class selection - ckeditor

I merged the stylesheetparser and the stylescombo plugins and want to select mutiple classes from the combo. I made some changes in the onOpen and the onClick functions:
onOpen: function() {
var selection = editor.getSelection(),
selectedElement = selection.getSelectedElement(),
selectedRanges = !selectedElement && selection.getRanges(),
selectedText = !selectedElement && selection.getSelectedText(),
nativeRange,
elementPath = editor.elementPath(),
element,
counter = [ 0, 0, 0, 0 ];
this.showAll();
this.unmarkAll();
for ( var name in styles ) {
var style = styles[ name ],
type = style._.type;
if(type == CKEDITOR.STYLE_OBJECT && (selectedElement || selectedText))
element = !selectedText ? selectedElement : selectedText;
else if((type == CKEDITOR.STYLE_BLOCK || type == CKEDITOR.STYLE_INLINE) && !selectedText && !selectedElement && selectedRanges[ 0 ] && selectedRanges[ 0 ].getCommonAncestor( 1 ))
element = selectedRanges[ 0 ].getCommonAncestor( 1 ).getAscendant( style.element );
else if(type == CKEDITOR.STYLE_INLINE && selectedText && !selectedElement)
element = selectedText;
if(element != null) {
if(style.checkApplicable( elementPath, editor, editor.activeFilter )) {
counter[ type ]++;
var classes = !selectedText ? element.getAttribute( 'class' ) : null,
classArr = classes != null ? classes.split(' ') : [];
if(classArr.length > 0) {
for(var i = 0; i < classArr.length; i++) {
if(classArr[i] == style._.definition.attributes['class'])
this.mark( name );
}
}
}
else
this.hideItem( name );
}
}
if ( !counter[ CKEDITOR.STYLE_BLOCK ] )
this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_BLOCK ) ] );
if ( !counter[ CKEDITOR.STYLE_INLINE ] )
this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_INLINE ) ] );
if ( !counter[ CKEDITOR.STYLE_OBJECT ] )
this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_OBJECT ) ] );
},
onClick: function( value ) {
editor.focus();
editor.fire( 'saveSnapshot' );
var style = styles[ value ],
type = style._.type,
selection = editor.getSelection(),
selectedElement = selection.getSelectedElement(),
selectedRanges = !selectedElement && selection.getRanges(),
selectedText = !selectedElement && selection.getSelectedText(),
element;
if(type == CKEDITOR.STYLE_OBJECT && (selectedElement || selectedText))
element = !selectedText ? selectedElement : selectedText;
else if((type == CKEDITOR.STYLE_BLOCK || type == CKEDITOR.STYLE_INLINE) && !selectedText && !selectedElement && selectedRanges[ 0 ] && selectedRanges[ 0 ].getCommonAncestor( 1 ))
element = selectedRanges[ 0 ].getCommonAncestor( 1 ).getAscendant( style.element );
else if(type == CKEDITOR.STYLE_INLINE && selectedText && !selectedElement)
element = selectedText;
if(element != null) {
var classes = !selectedText ? element.getAttribute( 'class' ) : null,
classArr = classes != null ? classes.split(' ') : [],
selClass = style._.definition.attributes['class'],
styleClasses = CKEDITOR.tools.clone( style );
if(classArr.length > 0 && contains(classArr, selClass) && !selectedText) {
var newClassArr = new Array();
for(var i = 0; i < classArr.length; i++) {
if(classArr[i] != selClass)
newClassArr.push(classArr[i]);
}
if(newClassArr.length == 0) {
editor.removeStyle( styleClasses );
}
else {
styleClasses._.definition.attributes['class'] = newClassArr.join(' ');
editor.applyStyle( styleClasses );
}
}
else {
classArr.push(selClass);
styleClasses._.definition.attributes['class'] = classArr.join(' ');
editor.applyStyle( styleClasses );
}
}
editor.fire( 'saveSnapshot' );
},
It works for block elements and images (didn't checked fake elements), you can select and deselect all classes you want. But I have some trouble with inline elements.
If I click inside a block element, it lists all classes for this element and I can select/deselect what I want/need. If I click inside an inline element, nothing happends. Can getAscendant() not find inline element tags?
If I select text, it lists all classes for inline elements. But I want span classes only and not e.g. strong classes. Classes for the strong tag should only available if I select a strong element. Is it possible? How can I differentiate different inline elements?
Why anchors are objects and not inline elements? If I double click an anchor and close the link dialog, I can select an anchor class.
How to disable the combo, if no classes are available? I can not find the right place.
How to disable the combo close on a class selection? If the selected class is set after close, forget this question - I can live with it :-)
Here is a demo: http://webutler.de/test/index.php?lang=en
The complete file: test/plugins/cssclasscombo/plugin.js
The plugin as zip: test/plugins/cssclasscombo.zip
If you try the plugin, set
config.contentsCss = ['contents.css']; // <= it reads the classes from this file
config.extraPlugins = 'cssclasscombo';
config.removePlugins = 'stylescombo';
config.stylesSet = [];
config.allowedContent = true;
// the plugin works with indent and justify classes =>
config.justifyClasses = [ 'alignleft', 'aligncenter', 'alignright', 'alignjustify' ];
config.indentClasses = [ 'indent1', 'indent2', 'indent3', 'indent4', 'indent5' ];
to your config and use this CSS file: http://www.webutler.de/test/contents.css
Thanx for help

It's not perfect, but the plugin works now. If you can need it, here is the download:
http://webutler.de/download/ckeditor_plugins/cssclasscombo.zip
Settings in your config.js:
config.removePlugins = 'stylescombo';
config.extraPlugins = 'cssclasscombo';
config.stylesSet = [];
config.contentsCss = ['contents.css']; // <= classes are read from this file(s)

Related

Is there a way I can make my script more efficient?

I have created the below script to add a timestamp when a cell equals a specific value. This script repeats for each row but it is not efficient. How can I make this simpler and quicker? Below is an extract of the script, it repeats for each row
function MyFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName('Overview')
var cell = sheet.getRange('H3').getValue()
var sent = sheet.getRange('p3').getValue()
if (cell == "Full" && sent == "") {
sheet.getRange('p3').setValue(new Date())
}
else if (cell == "Open" && sent == "") {
sheet.getRange('p3').setValue("")
}
}
Try this.
function MyFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Overview');
// get range H3:P were H=8, P=16, 9 columns total or index 0 to 8
var data = sheet.getRange(3,8,sheet.getLastRow()-2,9).getValues(); // get range H3:P
var i = 0;
var row = null;
for( i=0; i<data.length; i++ ) {
row = data[i];
if( ( row[0] === "Full" ) && ( row[8] === "" ) ) {
row[8] = new Date();
}
// Your else doesn't do anything if blank set blank ??
row.splice(0,8); // extract only column P
}
sheet.getRange(3,16,data.length,1).setValues(data);
}
Try using setvalues() method of class range
function MyFunction() {
const ss = SpreadsheetApp.getActive()
const sh = ss.getSheetByName('Overview');
const rg = sh.getDataRange();
const vs = rg.getValues();
let vo = vs.map(r => {
if( r[7] == "Full") r[15]=new Date()
if( r[7] == "Open") r[15]='';
return [r[15]];
});
sh.getRange(2,16,vo.length,1).setValues(vo);
}

Data Validation with possible loops

This is a functioning script for dynamic data validation set based on some old youtube videos
It's slow and I'm not sure where there might be a loop that I can remove
Had never used scripts until 4 hours ago; can anyone please make this run faster
Any advice appreciated!
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var datass = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Reference Sheet");
if(ss.getName() == "Test Sheet" && ss.getActiveCell().getColumn() == 10 && ss.getActiveCell().getRow() > 7){
ss.getActiveCell().offset(0, 1).clearContent().clearDataValidations();
var materials = datass.getRange(1, 1, 1, datass.getLastColumn()).getValues();
var materialIndex = materials[0].indexOf(ss.getActiveCell().getValue()) + 1;
if(materialIndex != 0){
var validationRangeMU = datass.getRange(2, materialIndex, datass.getLastRow());
var validationRuleMU = SpreadsheetApp.newDataValidation().requireValueInRange(validationRangeMU).build();
ss.getActiveCell().offset(0, 1).setDataValidation(validationRuleMU);
}
}
if(ss.getName() == "Test Sheet" && ss.getActiveCell().getColumn() == 15 && ss.getActiveCell().getRow() > 7){
ss.getActiveCell().offset(0, 1).clearContent().clearDataValidations();
var materials = datass.getRange(1, 1, 1, datass.getLastColumn()).getValues();
var materialIndex = materials[0].indexOf(ss.getActiveCell().getValue()) + 1;
if(materialIndex != 0){
var validationRangeMU = datass.getRange(2, materialIndex, datass.getLastRow());
var validationRuleMU = SpreadsheetApp.newDataValidation().requireValueInRange(validationRangeMU).build();
ss.getActiveCell().offset(0, 1).setDataValidation(validationRuleMU);
}
}
if(ss.getName() == "Test Sheet" && ss.getActiveCell().getColumn() == 20 && ss.getActiveCell().getRow() > 7){
ss.getActiveCell().offset(0, 1).clearContent().clearDataValidations();
var materials = datass.getRange(1, 1, 1, datass.getLastColumn()).getValues();
var materialIndex = materials[0].indexOf(ss.getActiveCell().getValue()) + 1;
if(materialIndex != 0){
var validationRangeMU = datass.getRange(2, materialIndex, datass.getLastRow());
var validationRuleMU = SpreadsheetApp.newDataValidation().requireValueInRange(validationRangeMU).build();
ss.getActiveCell().offset(0, 1).setDataValidation(validationRuleMU);
}
}
Try this:
Just taking maximum advantage of the event object
function onEdit(e) {
var idx = [10, 15, 20].indexOf(e.range.columnStart)
if (e.range.getSheet().getName() == "Test Sheet" && ~idx && e.range.rowStart > 7) {
var rsh = e.source.getSheetByName("Reference Sheet");
e.range.offset(0, 1).clearContent().clearDataValidations();
var materials = rsh.getRange(1, 1, 1, rsh.getLastColumn()).getValues();
var materialIndex = materials[0].indexOf(e.value) + 1;
if (materialIndex != 0) {
var validationRangeMU = rsh.getRange(2, materialIndex, rsh.getLastRow());
var validationRuleMU = SpreadsheetApp.newDataValidation().requireValueInRange(validationRangeMU).build();
e.range.offset(0, 1).setDataValidation(validationRuleMU);
}
}
}

Date "less but not empty" custom search in free-jqgrid

I am using free-jqgrid 4.15.4 for showing the data. There i have a need to search date column with Date less but not empty filter, but it is not filtering correctly. In result it gives me date which are greater than searched date.
Below code is used for custom filter in date column:
customSortOperations: {
dlne: {
operand: "<!=''",
text: "Date less but not empty",
filter:function (options) {
var p = this.p, iCol = p.iColByName[options.cmName], cm = p.colModel[iCol],
newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
cm.formatoptions.newformat :
$(this).jqGrid("getGridRes", "formatter.date.newformat"),
srcformat = cm.formatoptions != null && cm.formatoptions.srcformat ?
cm.formatoptions.srcformat :
$(this).jqGrid("getGridRes", "formatter.date.srcformat"),
fieldData = $.jgrid.parseDate.call(this, srcformat, options.item[options.cmName]),
searchValue = $.jgrid.parseDate.call(this, newformat, options.searchValue);
var retFData = convertD(fieldData), t = new Date(retFData);
if ((retFData.getFullYear() < searchValue.getFullYear()) && (retFData.getMonth() < searchValue.getMonth()) && (retFData.getDate() < searchValue.getDate())) {
return true
}
}
},
}
The convert function that I am using for converting string into date format, is written below:
function convertD(dateField) {
var date = new Date(dateField),
mnth = ("0" + (date.getMonth() + 1)).slice(-2),
day = ("0" + date.getDate()).slice(-2);
// year= (date.getFullYear())
var retVal = [day, mnth, date.getFullYear()].join("/");
return retVal;
}
I have taken the idea from here and made some changes but seems no avail. So requesting community to help on this.
The code of dlne could be fixed to for example the following:
dlne: {
operand: "<!=''",
text: "Date less but not empty",
filter: function (options) {
var p = this.p, iCol = p.iColByName[options.cmName], cm = p.colModel[iCol],
newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
cm.formatoptions.newformat :
$(this).jqGrid("getGridRes", "formatter.date.newformat"),
srcformat = cm.formatoptions != null && cm.formatoptions.srcformat ?
cm.formatoptions.srcformat :
$(this).jqGrid("getGridRes", "formatter.date.srcformat"),
fieldData, searchValue;
// the exact condition to test for "empty" depend on the format of your data
if (!options.item[options.cmName]) {
return false; // ignore empty data
}
fieldData = $.jgrid.parseDate.call(this, srcformat, options.item[options.cmName]);
searchValue = $.jgrid.parseDate.call(this, newformat, options.searchValue);
return fieldData.getFullYear() < searchValue.getFullYear() ||
(fieldData.getFullYear() === searchValue.getFullYear() &&
fieldData.getMonth() < searchValue.getMonth()) ||
(fieldData.getFullYear() === searchValue.getFullYear() &&
fieldData.getMonth() === searchValue.getMonth() &&
fieldData.getDate() < searchValue.getDate());
}
}
see https://jsfiddle.net/OlegKi/51vfn4k9/11/

Paging property missing in Status

In latest version of LINQ to Twitter v2.1.08 there is no longer support for paging. How do I get a certain page without page property?
Cheers
int curPageIndex=5;
string pageindex="5";
string cmd = "next";
using (var twitterCtx = new TwitterContext(myauth))
{
try
{
// set up the "main query"
IQueryable<Status> test = from tweet in twitterCtx.Status select tweet;
switch (cmd)
{
case "prev":
test = pageindex.Length > 0
? test.Where(p => p.Type == StatusType.Home && p.Page == curPageIndex)
: test.Where(p => p.Type == StatusType.Home);
break;
case "next":
test = pageindex.Length > 0
? test.Where(p => p.Type == StatusType.Home && p.Page == curPageIndex)
: test.Where(p => p.Type == StatusType.Home);
break;
default:
//
test = test.Where(p => p.Type == StatusType.Home);
break;
}
Solution: Changed Page parameter to SinceID and MaxID
//Get the statusids in the query, add or subtract so you skip current id's
ulMaxId = test.Min(status => ulong.Parse(status.StatusID)) - 1;
ulSinceID = test.Max(status => ulong.Parse(status.StatusID)) + 1;
//Return ID above and use them in future calls (below)
//Now you can navigate timelines, depending if you are stepping forward or backwards
? test.Where(p => p.Type == StatusType.Home && p.SinceID == ulong.Parse(sinceid)
...
? test.Where(p => p.Type == StatusType.Home && p.MaxID == ulong.Parse(maxid))

extract content method of range skips tags in CKEditor

I want to make sidebar plugin in CKEditor.when I select text with bold and itallic tag ,than extract content skip that tags ,and returns just text .I want all selected text including all tags.
This is my code:
function sidebar(editor){
var selection = editor.getSelection();
if (selection.getSelectedText() != "") {
var ranges = selection.getRanges();
var pNode = editor.document.createElement('p');
var extractedContent = ranges[0].extractContents();
pNode.append(extractedContent);
var customNode = editor.document.createElement('cdl:sidebar');
customNode.append(pNode);
var sidebarHolder = editor.document.createElement("sidebarholder");
sidebarHolder.append(customNode);
var nodeHtml = sidebarHolder.getHtml();
selection.selectRanges(ranges);
editor.insertHtml(nodeHtml);
}
else {
showErrorMessage("Selection is not proper");
}
}
You can get multi selection text using ckeditor walk.
// Walker searching for guardElements.
var walker = new CKEDITOR.dom.walker( range );
var start = bookmarks[ i ].startNode,
end = bookmarks[ i++ ].endNode;
walker.evaluator = function( node )
{
return !! ( node.type == CKEDITOR.NODE_ELEMENT
&& node.getName() in guardElements
&& !( node.getName() == ( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' )
&& node.getParent().type == CKEDITOR.NODE_ELEMENT
&& node.getParent().getName() == 'blockquote' )
// Element must be fully included in the range as well. (#6485).
&& node.getPosition( start ) & CKEDITOR.POSITION_FOLLOWING
&& ( ( node.getPosition( end ) & CKEDITOR.POSITION_PRECEDING + CKEDITOR.POSITION_CONTAINS ) == CKEDITOR.POSITION_PRECEDING ) );
};
Use walker.js
http://docs.cksource.com/ckeditor_api/symbols/src/core_dom_walker.js.html

Resources