blessed icon indicating copy to clipboard operation
blessed copied to clipboard

duplication of input

Open kicumkicum opened this issue 10 years ago • 10 comments

  1. focus to textarea
  2. enter charectes abc
  3. focus to List
  4. hide List and focus to another List
  5. focus to textarea
  6. enter charectes abc, but result aabbcc

I see this behavior in my app vknplayer, after update blessed from 0.0.47 to 0.0.48 What could be the reason?

kicumkicum avatar Mar 13 '15 19:03 kicumkicum

@kicumkicum, are you using the latest blessed? There was a race condition with binding key listeners on textareas a little while ago, but it was fixed.

chjj avatar Mar 19 '15 11:03 chjj

I'm also seeing this kind of behavior with Blessed 0.1.7.

If I have two textbox elements, boxOne and boxTwo and define an on('click'... event that does nothing, i.e.:

boxTwo.on('click', function(data) {
  // Nothing
});

If boxOne was focused for input and I now click onto boxTwo, boxTwo does not receive focus and any further typing in boxOne will be duplicated.

Additional calls to a focus() method on another element can cause this input to be quadruplicated.

Not quite sure whats going on here but I will be happy to provide more info.

KalenAnson avatar Jul 16 '15 18:07 KalenAnson

I use blessed 0.1.81 I have two blessed.list and one blessed.textarea I loging remove listener in readInput and add listener in nextTick. task keys:

  • start app - show first list. Hide second list. Show textarea. Focus in textarea
  • set focus to first list - 'remove listener', 'add listener', 'remove listener'
  • show second list, hide filst list - 'remove listener', 'add listener'
  • show first list, hide second list - 'remove listener', 'add listener'
  • set focus to textarea - 'add listener'
  • result - textarea have two listeners and dubl symbols

kicumkicum avatar Sep 26 '15 20:09 kicumkicum

Any update on this?

kkirby avatar Nov 12 '15 16:11 kkirby

I revert this commit https://github.com/chjj/blessed/commit/b42308c7cc3e544821254a0095082d22b60f5af9 and work for my, but i don't know what i'm doing.

m4rky77 avatar Dec 23 '15 03:12 m4rky77

I'm still getting this issue, and I think it happened because I have multiple controls listening for the escape key on input, and then refocusing a textbox on this happening. When I removed this callback, it stopped happening.

program.key('escape', function() {
  text.focus();
});

blessed 0.1.81

bradparks avatar Oct 21 '16 02:10 bradparks

In case anyone else has this issue I created a workaround that does not require a fork. You can use this function to add a working inputFocus and inputBlur to a textbox instance. This will cleanup the listeners on blur that cause the duplication.

export function AddBlurToTextBox(textBox, handlers) {
	textBox.inputFocus = () => {
		textBox.inputBlur()
		textBox.addHandlers()
		textBox.focus()
	}

	textBox.addHandlers = () => handlers()

	textBox.inputBlur = () => {
		textBox.removeListener('keypress', textBox.__listener);
		delete textBox.__listener;

		textBox.removeListener('blur', textBox.__done);
		delete textBox.__done;
		textBox.screen.focusPop(textBox)
	}
}

Usage: Note you must add all your handlers to the callback so they can be reattached on focus

AddBlurToTextBox(input, () => {
        input.on('keypress', (ch, key) => {
                 //do something
	})
})

Clearly not ideal -- but I don't want to own this code by forking it

acunniffe avatar Oct 15 '18 17:10 acunniffe

For me , removing the explicit focus handler for the textbox and setting the option inputOnFocus: true solves this issue.

rajasegar avatar Aug 16 '20 11:08 rajasegar

I have the same Problem. but i use it only for an intro and i destroy after that the screen. after that i use inquirer for questions and dubble input. @acunniffe i dont now but i cant get working your fix for me.

module.exports = ({screen, box, image, bigtext}, callback) => {
	const sc = screen({
		smartCSR: true
	});

	const bx = box({
		parent: sc,
		height: "100%",
		width: "100%",
		optimierung: "cpu",
	});


	sc.append(bx);

	let i = 100;

	let img = image({
		parent: bx,
		top: 0,
		left: i + "%",
		width: "34%",
		height: "100%-14",
		type: "ansi",
		ascii: "density",
		file: __dirname + "/../../img/Mond.png",
	});

	bigtext({
		parent: bx,
		content: "MoonShop",
		top: "100%-14",
		style: {
			fg: "white",
		},
		left:"center",
		align:"center",
		valign:"middle",
	});



	function AddBlurToTextBox(sc, handlers) {
		sc.inputFocus = () => {
			sc.inputBlur();
			sc.addHandlers();
			sc.focus();
		};

		sc.addHandlers = () => handlers();

		sc.inputBlur = () => {
			sc.removeListener("keypress", sc.__listener);
			delete sc.__listener;

			sc.removeListener("blur", sc.__done);
			delete sc.__done;
			sc.screen.focusPop(sc);
		}
	}

	AddBlurToTextBox(sc, () => {

	});


	function intro(){
		if(i > 33){
			i--;
			img.left = i + "%";
			sc.render();
			setTimeout(intro,50);
		} else {
			setTimeout(() => {
				sc.destroy();
				console.clear();
				callback();
			}, 4000);
		}
	}
	intro();
};


Trackhe avatar Sep 05 '20 12:09 Trackhe

For Whatever it's worth, I spent quite a while battling this problem and finally came up with a working solution based on @acunniffe's code. My slightly modified version is below.

function AddBlurToTextBox(textBox, handlers) {
        textBox.inputFocus = () => {
                textBox.inputBlur()
                textBox.addHandlers()
                textBox.focus()
        }

        textBox.addHandlers = () => handlers()

        textBox.inputBlur = () => {
                setImmediate(() => {
                    textBox.removeListener('keypress', textBox.__listener);
                    delete textBox.__listener;

                    textBox.removeListener('blur', textBox.__done);
                    delete textBox.__done;
                });
        }
}

In my code, I just call the inputBlur() in my submit handler. - when the input is focused again it behaves normally.

The issue seems to be that TextArea is adding it's listeners in a nextTick() (which is really setImmediate()) - which means just removing them doesn't work because they don't exist yet. Putting the removal in a setImmediate makes the removal happen after they are actually added. No more key duplication. :)

jayk avatar Oct 31 '23 04:10 jayk