ONLYOFFICE 7.0: online forms, password protection in sheets, collaboration improvements and much more
ONLYOFFICE 7.0 released

How to keep InputHelper active on "." keypress

Hi! This is a how-to question!

I have a non-visual plugin based on the autoComplete sample plugin here: ONLYOFFICE Api Documentation - Plugin examples

In my usage I want the user to be able to enter object.property values separated with dot-notation - so I have options including “foo.moo” and “foo.zoo”, and as a user types “foo.” I should filter down and display those two options.

What I’m finding is that as soon as the user hits the “.” character, event_onInputHelperClear fires and I stop receiving event_onInputHelperInput events, so my auto-complete behavior stops working.

Is there a way to keep the input helper active after the user hits “.” so my auto-complete options can include strings in dot-notation?

Document Server version:
OO Docs Developer Edition
[Document editor version shows up as 7.0.0]

Installation method:

OS:

  • MacOS, running the doc server via docker and serving the main webpage and plugin HTML from a separate Tomcat instance

Browser version:

  • Chrome Version 99.0.4844.51 (Official Build) (x86_64)

Hello @pablissimo
Is it possible to provide us with your custom plugin? So we are able to check it out.
Also please provide us with recorded videofile of the issue demonstration.

Hi Alexadre! Thanks for responding.
I don’t see an option to upload a zip file to the forum but I started with the example_autocomplete sample from github: sdkjs-plugins/example_autocomplete at master · ONLYOFFICE/sdkjs-plugins · GitHub

I removed scripts/dictionary.js altogether, updated index.html to no longer attempt to load that resource, and changed code.js to

  • define the “dictionary” array inline as a simple set of 4 strings, with dots in them
  • modify getAutoComplete to be a very simple for-loop to determine the list of matches, prompted by a user typing a string starting with “{{”
  • added some console.warn(…) statements to make it easier to see what’s going on.

Here’s the reworked version of that code:

(function(window, undefined){

	window.isInit = false;

	window.Asc.plugin.init = function(text)
	{
		if (!window.isInit)
		{
			window.isInit = true;

			window.Asc.plugin.currentText = "";
			window.Asc.plugin.createInputHelper();
			window.Asc.plugin.getInputHelper().createWindow();
		}
	};

	window.Asc.plugin.button = function(id)
	{
		this.executeCommand("close", "");
	};
	
	window.Asc.plugin.inputHelper_onSelectItem = function(item)
	{
		if (!item)
			return;

		window.Asc.plugin.executeMethod("InputText", [item.text, window.Asc.plugin.currentText]);
		window.Asc.plugin.getInputHelper().unShow();
	};

	window.Asc.plugin.event_onInputHelperClear = function()
	{
            window.console.warn("input helper clear fired");
            // If you add a debugger statement here and examine the stack after
            // pressing the "." key, you see 
            // - ws.onkeypress calls
            // - obfuscated method [name "OUa"], seems to check for event reporting charset
            //   value 46 [period/full stop]
            //   https://www.w3schools.com/html/html_charset.asp
            // - calls clear()
            // - posts inputHelperClear event to the plugin frame, which
            //   gets us into this method
            // debugger; 
		window.Asc.plugin.currentText = "";
		window.Asc.plugin.getInputHelper().unShow();
	};

	window.Asc.plugin.event_onInputHelperInput = function(data)
	{
            window.console.warn("input helper input fired");
            window.console.warn(data);
		if (data.add)
			window.Asc.plugin.currentText += data.text;
		else
			window.Asc.plugin.currentText = data.text;

		// correct by space
		var lastIndexSpace = window.Asc.plugin.currentText.lastIndexOf(" ");
		if (lastIndexSpace >= 0)
		{
			if (lastIndexSpace == (window.Asc.plugin.currentText.length - 1))
				window.Asc.plugin.currentText = "";
			else
				window.Asc.plugin.currentText = window.Asc.plugin.currentText.substr(lastIndexSpace + 1);
		}

		if (window.Asc.plugin.currentText.length < 3)
		{
			window.Asc.plugin.getInputHelper().unShow();
			return;
		}
		
		var variants = window.getAutoComplete(window.Asc.plugin.currentText);
		if (variants.length == 0)
		{
			window.Asc.plugin.getInputHelper().unShow();
		}
		else
		{
			var items = [];
			for (var i = 0; i < variants.length; i++)
			{
				items.push({ text : variants[i] });
			}

			window.Asc.plugin.getInputHelper().setItems(items);
			var _sizes = getInputHelperSize();
			window.Asc.plugin.getInputHelper().show(_sizes.w, _sizes.h, false);
		}
	};

	function getInputHelperSize()
	{
		var _size = window.Asc.plugin.getInputHelper().getScrollSizes();
		var _width = 150;// _size.w
		var _height = _size.h;
		var _heightMin = window.Asc.plugin.getInputHelper().getItemsHeight(Math.min(5, window.Asc.plugin.getInputHelper().getItems().length));

		if (_width > 400)
			_width = 400;
		if (_height > _heightMin)
			_height = _heightMin;

		_width += 30;

		return { w: _width, h : _height };
	}

	window.isAutoCompleteReady = false;
        window.g_dictionary = ["foo.aardvark", "foo.antelope", "fop.zebra", "moo.cow"];
	window.getAutoComplete = function(text)
	{
		if (!g_dictionary)
			return;

		window.isAutoCompleteReady = true;
		g_dictionary.sort();

		var textFound = text.toLowerCase();
                
                var matches = [];
                for (var i = 0; i < g_dictionary.length; i++) {
                    var textFound = text.toLowerCase(),
                        possibleMatch = "{{" + g_dictionary[i] + "}}";
                    if (possibleMatch.length >= textFound.length && 
                        possibleMatch.substring(0,textFound.length).toLowerCase() == textFound)
                    {
                        matches[matches.length] = g_dictionary[i]
                    }
                }
                return matches;
	};

})(window, undefined);

As noted in comments, I see that if the user types “{{foo.” I get an oninputhelperclear event from the “.” keypress.
If I add a debugger statement and look at the stack trace in the browser this comes from a keypress event which explicitly posts the inputhelperclear event message to the plugin frame.

Here’s a screenshot of that stack trace:

Here’s the source I see if I click on the “OUa” method:

[EDIT: See line 314811- labelled just “4811” in my screenshot - for the call to ‘clear()’]

It appears to be querying for an event character code value of 46 which is “.”: HTML Charset

I can record a video walking through this stuff if that’s helpful too, but I suspect this should give you everything you need.

As far as I can tell, dismissing the input helper on “.” keypress is a feature/default behavior and I’m basically asking if there’s any way to turn it off so I can continue to recieve the oninputhelperinput events after the “.” keypress and see the full string of text typed by the user up to the previous space

Thanks!

Hello @pablissimo
Sorry for the late reply. It took us some time to figure it out.
The fix for described situation (issue with “.” in input helper) will be placed in Document server v.7.2. The release is planned for summer.
Sorry for inconvenience.

Okay - thanks very much for letting me know! I’ll watch for the 7.2 release

Paul