I am trying to hook on CodeMirror and plug my own list of words to appear into the autocompletion. Based on this link https://stackoverflow.com/a/19269913/2892746 I tried to implement the following. I created a JSBin with it
The problem is that while my words do appear in the autocomplete, they are not filtered correctly. For example, I type "f", and then I do ctrl+space. But I get all the 3 words in the popup with "mariano" selected. I would expect to have only "Florencia" available and selected.
Any ideas what I could be doing wrong?
ps: yes, I would love to not change anyword hint and provide my own that simply matches my own words, but I don't know how to do that.
Thanks in advance!!
I have finally solved this myself. I am not a JS expert, but I share my solution in case it is useful for someone else.
IMPORTANT: I got the original code from this project. That project was with Angular and Angular-codemirror dependency. I was not using Angular anywhere in my app so I extracted and adjusted it to use it without Angular.
The goal is to be able to define a dictionary/map of words that will be used for the autocomplete. The solution is very simple. At a parent of myTextAreaId element you must create a span/div like this:
<div class="codeMirrorDictionaryHintDiv" codemirror-dictionary-hint="[ 'Soccer', 'Cricket', 'Baseball', 'Kho Kho' ]"></div>
Then...the code, will lookup the closest element with css class codeMirrorDictionaryHintDiv, will extract the attribute codemirror-dictionary-hint, will evaluate that in order to get a Javascript array out of it, and then simply set that as the input dictionary for the hint function.
The code is:
var dictionary = [];
try {
// JSON.parse fails loudly, requiring a try-catch to prevent error propagation
var dictionary = JSON.parse(
document.getElementById('myTextAreaId')
.closest('.codeMirrorDictionaryHintDiv')
.getAttribute('codemirror-dictionary-hint')
) || [];
} catch(e) {}
// Register our custom Codemirror hint plugin.
CodeMirror.registerHelper('hint', 'dictionaryHint', function(editor) {
var cur = editor.getCursor();
var curLine = editor.getLine(cur.line);
var start = cur.ch;
var end = start;
while (end < curLine.length && /[\w$]/.test(curLine.charAt(end))) ++end;
while (start && /[\w$]/.test(curLine.charAt(start - 1))) --start;
var curWord = start !== end && curLine.slice(start, end);
var regex = new RegExp('^' + curWord, 'i');
return {
list: (!curWord ? [] : dictionary.filter(function(item) {
return item.match(regex);
})).sort(),
from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end)
}
});
CodeMirror.commands.autocomplete = function(cm) {
CodeMirror.showHint(cm, CodeMirror.hint.dictionaryHint);
};
It's Happened When JS and Css Hint Files not Loaded!
for the resolve it you must import them into your app manually :
1- Import Js File In Your TypeScript File:
//CodeMirror
import 'codemirror/addon/hint/sql-hint';
import 'codemirror/addon/hint/show-hint';
2- Import Css File Into Your Css App File
//CodeMirror
#import "~codemirror/addon/hint/show-hint.css";
GoodLuck
Related
I am a novice in Sencha Touch 2 & Ext too. I have jquery knowledge, so I am relating few things similar for quick understanding but got stuck in selector query.
I am creating dynamic textfields like:
var autoSuggestField = 'people_' + counter; // suppose counter is looping 5 times
var field = new Ext.field.Text({
name: autoSuggestField,
itemId: 'testing', // just for testing
// itemId: autoSuggestField, // actual code
inputCls:'auto-suggest',
placeHolder:'Select People',
cls:'place-holder',
listeners: {
clearicontap:function(obj, e, eOpts) {
// tried option 1
var allPeople = Ext.ComponentQuery.query('.place-holder .auto-suggest');
console.log(allPeople); // console says '[]'
// tried option 2
var allPeople = Ext.ComponentQuery.query('.place-holder');
console.log(allPeople); // console says '[]'
// tried option 3
var allPeople = Ext.ComponentQuery.query('.auto-suggest');
console.log(allPeople); // console says '[]'
// tried option 4
var allPeople = Ext.ComponentQuery.query('#testing');
console.log(allPeople); // console says '[class , class, class]'
}
}
});
But I am looking for something:
// var allPeople = Ext.ComponentQuery.query('[name^=people_]'); // as we do jquery
Or anything similar to it, which should work. Please clear what I am doing wrong in option[1,2,3] as most of the post says that using id[option 4] is bad. An how can we achieve using [name^=] "which says any element starting with people_". Is it possible in Ext? Is it possible through REGEX?(just for an idea)
Please add explanations for better understanding of selectors.
Instead of looking for regular expressinons you can add a an extra config like type:'people' for all the people related textfiled components and you can query it using the
var allPeopleComponents = Ext.ComponentQuery.query('textfield[type=people]');
The above will return the array of components having type='people'.
Please take a look here and for better understanding of ComponentQuery options here
Hope it helps you.
I know this will probably a simple question, but I'm new to CQ5 and AEM in general.
I have a cq:Widget node which is a simple textfield.
<rowtitlevalue
jcr:primaryType="cq:Widget"
fieldLabel="Row Title Value"
name="./rowtitlevalue"
xtype="textfield"
disabled="true"/>
Now at the moment within my JavaScript, I'm currently accessing it via
var textfield = panel.findByType('textfield')[1];
which works fine (there's another textfield before this one, hence the 1 in the array.
MY QUESTION:
how do I look for this field using it's NAME attribute within my javascript.
Any help would be appreciated.
Also, I'm using this object to run the following:
if (show != undefined) {
textfield.enable();
textfield.show();
}
else if (show == undefined) {
textfield.disable();
textfield.hide();
}
The JavaScript is located within the Component Based ClientLibs.
And this is the Listener that I have under the checkbox that defines the value of SHOW within the javascript (which is working fine).
<listeners
jcr:primaryType="nt:unstructured"
loadcontent="function(field,rec,path){Ejst.toggleRowTitle(field);}"
selectionchanged="function(field,value){Ejst.toggleRowTitle(field);}"/>
Please let me know if you see any problems with this.
Appreciate it in advance
The CQ.Dialog API defines the getField( String name) method which returns a field with the given name. In case more than one field with the same name exists, it returns an array of those fields.
Thus finding parent of xtype dialog instead of panel as shown below would solve this.
Ejst.toggleRowTitle = function(checkbox) {
var dlg = checkbox.findParentByType('dialog');
var rowTitleField = dlg.getField('./rowtitlevalue');
// perform required operation on rowTitleField
}
i did something like that a few days ago and my solution was to make a js file on the same level of the component and with the same name of the component with the information that i need.
Something like this:
The file will be called rowtitlevalue.js and the content would be:
"use strict";
use(function() {
var data = {};
data.rowtitlevalueData = properties.get("rowtitlevalue");
//more properties if needed...
return {
data: data
}
});
then where i need to use it in javascript, i need the following tags:
<sly data-sly-use.data="rowtitlevalue.js">
<script type="text/javascript">
var myVariable = ${data.rowtitlevalueData};
</script>
</sly>
I recently installed Tridion 2011 SP1 with SDL module Translation Manager enabled.
Everything was working fine. Then I installed the Tridion 2011 Powertools, following the installation procedure.
When trying to reload the GUI (browser cache emptied and modification parameter instanciated for server element in WebRoot\Configuration\System.Config) I'm getting the following Javascript error :
SCRIPT5007: Unable to get value of the property 'getItemType': object is null or undefined
Dashboard_v6.1.0.55920.18_.aspx?mode=js, line 528 character 851
And here is the concerned JS line:
Tridion.TranslationManager.Commands.Save.prototype._isAvailable=function(c,a){var
e=c.getItem(0),f=$models.getItem(e),b=f.getItemType(),d=$models.getItem(this.getTmUri ())
The preceding Javascript lines are dealing with other TranslationManager commands, so I suppose it is a kind of TranslationManager commands registration or somehting.
Trying to browse my Tridion publications by selecting any folder/strucutreGroup will also give the same error and the right frame (content frame) will not display any Tridion items but simply display:
Loading ...
Has anyone already experienced similar issue ?
For now I have no other choice than commenting out the Powertools sections file
Tridion_Home\web\WebUI\WebRoot\Configuration\System.Config
Thank you,
François
Strange thing here is that it refers to Save command which is not intended to be called or used from Dashboard.
I`d suggest to disable JS minification (JScriptMinifier filter in System.config), as it will probably show more correct details.
Another useful thing would be this error call stack.
--
I was not able to reproduce an issue from initial question, but had following error when I installed PT:
PowerTools is not defined
which appears in
*\PowerTools\Editor\PowerTools\Client\Shared\Scripts\ProgressDialog\ProgressDialog.js where it tries to register PowerToolsBase namespace, instead of PowerTools.
I`ll be surprised if adding
Type.registerNamespace("PowerTools");
at the top of the file will fix a problem, as in my case it was breaking entire GUI no matter if TM included or no.
I did check *\PowerTools\Editor\PowerTools\Client\Shared\Scripts\ProgressDialog\ProgressDialog.js, but the line
Type.registerNamespace("PowerTools");
was already there, so not the problem here.
Also, I disabled the JS minification. Here are the main methods the UI is loading before getting the error:
...
PowerTools.Commands.ItemCommenting.prototype.isValidSelection = function (selection) {
//Use the existing Save command from the CME
return $cme.getCommand("Save")._isEnabled(selection);
}
...
/**
* Executes this command on the selection.
* Override this method to implement the actual functionality.
* #param {Tridion.Core.Selection} selection The current selection.
*/
Tridion.TranslationManager.Commands.SendForTranslation.prototype._execute = function SendForTranslation$_execute(selection)
{
var selectedItems = selection.getItems();
if (selectedItems.length == 1)
{
var job = $models.getItem(selectedItems[0]);
if (job)
{
if (job.isLoaded())
{
job.saveAndSend();
}
else
{
$log.warn("Unable to send an unloaded job?! {0}".format(job.getId()));
}
}
else
{
$log.warn("Unable to execute save-and-send-for-translation for this selection: {0}".format(selectedItems));
}
}
else
{
$log.warn("Unable to save-and-send-for-translation multiple items at a time.");
}
};
...
Tridion.TranslationManager.Commands.Save.prototype._isAvailable = function Save$_isAvailable(selection, pipeline)
{
var itemUri = selection.getItem(0);
var item = $models.getItem(itemUri);
var itemType = item.getItemType(); !!!!!!!!! fails on this line !!!!!! item is null or not an object
var config = $models.getItem(this.getTmUri());
if (pipeline)
{
pipeline.stop = false;
}
if (config && config.hasChanged() && (itemType == $const.ItemType.CATEGORY || itemType == $const.ItemType.FOLDER || itemType == $const.ItemType.STRUCTURE_GROUP || itemType == $const.ItemType.PUBLICATION))
{
if (pipeline)
{
pipeline.stop = true;
}
return true;
}
return this.callBase("Tridion.Cme.Command", "_isAvailable", [selection, pipeline]);
};
Ok. It`s clear now.
PowerTools.Commands.ItemCommenting is used in Dashboard Toolbar.
This command uses Save to check its availability.
In the same time TM thinks that "Save" will only be used on an ItemToolbar.
The difference between this toolbars which cause an issue is that Dashboard view could have any-length selection, when Item view will always have selection having one item (currently opened).
Opening empty dashboard selection is not yet made, ItemCommenting tries to check its availability, by calling Save, which calls all its extensions. And so far as selection is empty
var itemUri = selection.getItem(0);
will return null, as well as
$models.getItem(null)
What you can do, is to remove ItemCommenting extension command as it is done in tridion powertool trunk editor.config.
http://code.google.com/p/tridion-2011-power-tools/source/browse/trunk/PowerTools.Editor/Configuration/editor.config?spec=svn942&r=903 [592]
Hi everybody
I am using the tinymce format dropdown to apply custom styles to html elements. This is for users without html knowledge
One annoying thing for me is that when a user klicks at different styles they all get added and something like this may happen
<div class="floatleft floatright positionup positiondown">
In order to prevent this I searched for the responsible code which is in editor_template.js (compressed) but visible in editor_template_src.js
Is there maybe a way to rewrite this piece of javascript so that each applied style replaces the former?
_createStyleSelect : function(n) {
var t = this, ed = t.editor, ctrlMan = ed.controlManager, ctrl;
// Setup style select box
ctrl = ctrlMan.createListBox('styleselect', {
title : 'advanced.style_select',
onselect : function(name) {
var matches, formatNames = [];
each(ctrl.items, function(item) {
formatNames.push(item.value);
});
ed.focus();
ed.undoManager.add();
// Toggle off the current format
matches = ed.formatter.matchAll(formatNames);
if (!name || matches[0] == name)
ed.formatter.remove(matches[0]);
else
ed.formatter.apply(name);
ed.undoManager.add();
ed.nodeChanged();
return false; // No auto select
}
});
How about:
if (!name || matches[0] == name)
ed.formatter.remove(matches[0]);
else
ed.formatter.remove(matches[0]);
ed.formatter.apply(name);
Just a wild guess, haven't tried it myself.
This a lot of work to do, but it can be done.
I solved this issue writing a custom plugin and using a custom FormatterClass.
I suggest you try developing with tiny_mce_dev.js - this way you are able to track down problems to js classes.
Then you should have a look at the js-class Formatter.js and try to modify this one in order to fullfill your wishes.
The next step will be to save the mofied Formatter.js and make it part of your plugin, so that you can reset the real Formatter.js, cause i suggest not to change the tinymce core files.
Is there a quick way to get a list in JavaScript of the available Active X plugins?
I need to do a test to see if a plugin has been installed before I actually try to run it.
In effect I want to create a page that says 'Plugin Installed and properly Working' or have it fail gracefully.
I'm not sure how to have it fail gracefully if the plugin is not available.
Just try it.
try {
var plugin = new ActiveXObject('SomeActiveX');
} catch (e) {
alert("Error"); // Or some other error code
}
The object tag will display whatever is inside it if the object cannot be instantiated:
<object ...>
<p>
So sorry, you need to install the object. Get it here.
</p>
</object>
So, graceful failure is built-in and you don't need to use script at all.
Maybe this script can help
function detectPlugin() {
// allow for multiple checks in a single pass
var daPlugins = detectPlugin.arguments;
// consider pluginFound to be false until proven true
var pluginFound = false;
// if plugins array is there and not fake
if (navigator.plugins && navigator.plugins.length > 0) {
var pluginsArrayLength = navigator.plugins.length;
// for each plugin...
for (pluginsArrayCounter=0; pluginsArrayCounter < pluginsArrayLength; pluginsArrayCounter++ ) {
// loop through all desired names and check each against the current plugin name
var numFound = 0;
for(namesCounter=0; namesCounter < daPlugins.length; namesCounter++) {
// if desired plugin name is found in either plugin name or description
if( (navigator.plugins[pluginsArrayCounter].name.indexOf(daPlugins[namesCounter]) >= 0) ||
(navigator.plugins[pluginsArrayCounter].description.indexOf(daPlugins[namesCounter]) >= 0) ) {
// this name was found
numFound++;
}
}
// now that we have checked all the required names against this one plugin,
// if the number we found matches the total number provided then we were successful
if(numFound == daPlugins.length) {
pluginFound = true;
// if we've found the plugin, we can stop looking through at the rest of the plugins
break;
}
}
}
return pluginFound;} // detectPlugin
Call it using this for exemple
pluginFound = detectPlugin('Shockwave','Flash');
For Internet Explorer 11 you can use navigator.plugins JS API, but you need to add apropriate registrey keys in order for IE11 to detect it:
HKLM\SOFTWARE\Microsoft\Internet Explorer\NavigatorPluginsList
or for 64bit
HKLM\SOFTWARE\Wow6432\Microsoft\Internet Explorer\NavigatorPluginsList
e.g. for plugin with Name "ABC" and mime type "application/abc" :
add key HKLM\SOFTWARE\Wow6432\Microsoft\Internet
Explorer\NavigatorPluginsList\ABC
create subkey for each custom MIME
type supported by the plugin, using the MIME type value as the name
of the subkey e.g. "application/abc"
Then checking for the plugin existence is done using this code:
var plugin = navigator.plugins["<your plugin activex id>"];
if(plugin) {
//plugin detected
} else {
//plugin not found
}
More on this here: http://msdn.microsoft.com/en-us/library/ie/dn423948(v=vs.85).aspx