Extjs panel. Keyboard events - javascript

I have a panel which I am rendering using following code.
new Ext.Panel({
id: 'textPanel',
height: 1000,
width: 1200,
renderTo: Ext.getBody(),
html:"An HTML fragment, or a DomHelper specification to use as the layout element content. The HTML content is added after the component is rendered, so the document will not contain this HTML at the time the render event is fired. This content is inserted into the body before any configured contentEl is appended."
});
And then I want to listen to event when an enter key is pressed. So, I am creating a KeyMap as follows...
var map = new Ext.KeyMap(Ext.getCmp('textPanel').body, {
key: Ext.EventObject.ENTER,
fn: onKeyPress,
// handler: onKeyPress,
scope: this
});
But the onKeyPress function is not being called.
I have already tried using
Ext.getCmp('textPanel').body.dom,
Ext.getCmp('textPanel').el.dom,
Ext.getCmp('textPanel').el
instead of
Ext.getCmp('textPanel').body
with no success.
If I use "document" there then the onKeyPress function is called. i.e.
var map = new Ext.KeyMap(document, {
key: Ext.EventObject.ENTER,
fn: onKeyPress,
// handler: onKeyPress,
scope: this
});
This works perfectly but I don't want to listen to whole document.
How can I listen to just the panel?

In extjs 3.4, if you want to use KeyMap then you need to first set focus on the panel element, otherwise key events will always fire at document level hence you will not able to listen for key events on panel (that's why you were able to listen key events on document only)
But in extjs there isn't any way to set focus on panel, so therefore you will need to create a custom panel class which can set focus to itself and listen key events
Ext.namespace('Saket');
Saket.FocusPanel = Ext.extend(Ext.Panel, {
onRender : function()
{
Saket.FocusPanel.superclass.onRender.apply(this, arguments);
// this element allows the Window to be focused for keyboard events
this.focusEl = this.el.createChild({
tag: 'a', href:'#', cls:'x-dlg-focus',
tabIndex:'-1', html: ' '});
this.focusEl.swallowEvent('click', true);
this.getEl().on({
click : this.focus,
scope : this
});
},
focus : function()
{
this.focusEl.focus();
}
});
new Saket.FocusPanel({
id: 'textPanel',
height: 200,
width: 300,
renderTo: Ext.getBody(),
html:"An HTML fragment, or a DomHelper specification to use as the layout element content. The HTML content is added after the component is rendered, so the document will not contain this HTML at the time the render event is fired. This content is inserted into the body before any configured contentEl is appended.",
keys: {
key: Ext.EventObject.ENTER,
fn: function() {alert('bingo');},
scope: this
}
});
Demo: http://jsfiddle.net/silentsakky/PdyqW/3/

Add a listeners for keydown on the panel's element using getEl():
Ext.getCmp('textPanel').getEl().on('keydown', function(f, e) {
if (e.getKey() === Ext.EventObject.ENTER)
{
//do whatever you want here
}
});

Related

How to restrict TAB navigation within the one window widget?

I have a Webix modal window with a form with several inputs:
var form = {
view:"form",
borderless:true,
elements: [
{ view:"text", label:'Login', name:"login" },
{ view:"text", label:'Email', name:"email" },
{
view:"button", value: "Submit", click:function(){
console.log(this.getParentView().getValues())
}}
]
};
The following sample there's a window that illustrates the current behavior:
http://webix.com/snippet/4bd116bb
If I use TAB navigation, focus goes out the window from the last in-window control. Is there a way to localize TAB navigation within the window once the focus gets in?
Code can catch onFocusChange event and move focus back if target is outsideo of the window.
webix.attachEvent("onFocusChange", function(target){
if (!target || target.getTopParentView() != $$("win"))
webix.delay(function(){
webix.UIManager.setFocus($$("win").getBody().elements.login);
});
});
http://webix.com/snippet/7db250dd

CKEDITOR On element append

I can't seem to find an event in the documentation that will trigger when a specific element has been inserted into the HTML of a textarea.
For example if the user makes text bold, I would like to trigger an event when the 'b' tag is added into the HTML; as well as any other tag.
You can use change event and check if b is present in input:
var editor = CKEDITOR.inline(element, {
resize_enabled: false,
skin: 'rich-text,' + RX_RICH_TEXT.ckeditor.skinPath,
on: {
change: function () {
var dom = this.getData();
if (dom.includes('<b>')) {
// your logic
}
},

How can I bind to the select2 change event and get the selected value

I have a select element which is decorated by Select2 via the SonataAdminBundle.
I am trying to listen to the change event. The ID of my select tag is "categorySelector".
This does not work:
var test = $('#categorySelector');
$(test).change(function() {
var theSelection = $(test).select2("val");
//$('#selectedID').text(theID);
console.log(theSelection);
});
How do I do this?
I think this should work for you...
$('#categorySelector').on("change", function(e) {
var theSelection = e.val();
console.log(theSelection);
});
All public events are relayed using the jQuery event system, and they are triggered on the element that Select2 is attached to. You can attach to them using the .on method provided by jQuery:
$('#categorySelector').on('select2:select', function (e) {
// Do something
});
When select2:select is triggered, data from the selection can be accessed via the params.data
In param.data you received object like:
{selected: true, disabled: false, text: "India", id: "101", title: "", …}
then you can simple apply text or id property.
$('#categorySelector').on('select2:select', function (e) {
var theSelection = e.params.data.id;
console.log(theSelection );
});

ListView doesn't fire selectionchanged

My HTML:
<div id="listViewBoxOffice"
data-win-control="WinJS.UI.ListView"
data-win-options="{ itemTemplate: select('#movieThumbnailTpl'), selectionMode: 'single' }">
</div>
My Javascript:
WinJS.UI.Pages.define("/pages/home/home.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
api.getBoxOffice().done(this.boxOffice, this.errBoxOffice);
listViewBoxOffice.winControl.addEventListener('selectionchanging', this.selectionchanging);
listViewBoxOffice.winControl.addEventListener('selectionchanged', this.selectionchanged);
},
boxOffice: function (movies) {
var list = new WinJS.Binding.List(movies);
listViewBoxOffice.winControl.itemDataSource = list.dataSource;
},
errBoxOffice: function (err) {
debugger;
},
selectionchanged: function (evt) {
console.log('changed');
},
selectionchanging: function (evt) {
console.log('changing');
}
});
My problem:
The event selectionchanged is never fired. The event selectionchanging is fired but with bad value in newSelection.
While the documentation isn't as clear about this as I think it should be, you'll need to set the tapBehavior property to "toggleSelect" so that an item is fully selected. By default, the behavior is invokeOnly and with that it doesn't fully select the item. It clicks, but isn't selected.
There's a decent example located in the MSDN documentation.
If you store off a copy of the listViewBoxOffice instance, then from the events, you can get the current list via a promise:
listViewBoxOffice.selection.getItems().done(function(items) {
// do something with the items...
});
To check wheather the selectionchanged event is working or not Right click on the listview item.I think when we just only click on the listview item it needs iteminvoke event and for selection we need to right click on the item.
Following is the code snipet which is firing the selectionchanged event
<div id="UserListView" data-win-control="WinJS.UI.ListView" style="border-top: 5px solid #000; min-width:500px;"
data-win-options="{
selectionMode:'multi',
itemTemplate:select('#itemsList'),
layout:{
type:WinJS.UI.GridLayout}}"
>
</div>
and in the js
UserListView.addEventListener("selectionchanged", selection);
function selection(evt) {
var test = "testing";
}
set the breakpoint and you can check in the evt the type="selectionchanged"
please try using Item invoked. Here's the Msdn link
Item invoked Winjs Listview
And try changing the selection accordingly.
Also if this does not work or you want selection changed only then Please post in the Template that you have designed. Will need to go through the entire code :)

AngularJS Directive - How to let an event only be triggered once if otherwise it'll be triggered on multiple elements?

This is what I currently have:
http://plnkr.co/edit/L9XqEyOtRSGHc9rqFPJX
I am trying to make it so that when I press the down key for the first time, the focus will move onto #div2; repeating the action should have the focus moving onto li > div:first-child.
In the demo however, upon the first time the down key is pressed, the focus will jump to li > div:first-child directly, because both the key-map on #div1 and #div2 captured the same keydown event, so the focus jumps from #div1 to #div2 then #div2 to li > div:first-child in one go.
How should I solve this issue or, better yet, is there anyway to improve how the codes are structured? I am not sure whether those event listeners are attaching to the DOM in the optimal fashion right now.
You are attaching a keydown handler to the document for each element. I don't think stopPropagation() will do any good because the two handlers are on the same element and it won't propagate up from document but both will still fire.
I suggest re-evaluating how you're approaching it. You only wish the element with the focus class to have it's options evaluated, so why not wrap all those elements in an element with your directive and have it listen only once and choose the element to act on.
(plunker)
<div key-mapped="">
<!-- children will apply key map of element with focus class -->
<div id="div1" class="focus" key-map="{
40: '#div2'
}">Hello</div>
directive:
}).directive('keyMapped', function($rootScope) {
return {
restrict: 'A',
link: function(scope, element, attr) {
angular.element(document).bind('keydown', function(event) {
var target = $(element).find('.focus');
console.log('target: ' + target);
var options = scope.$eval(target.attr('key-map'));
----EDIT----
Someone let me know if it's not a good practice, but you could always put the event handler on your directive object and ensure it is only set once and send a custom event to the element with the 'focus' class that you bind to in your link function.
(plunker)
}).directive('keyMap', function($rootScope) {
var dir = {
onKeydown: function(event) {
var element = document.querySelector('.focus');
var newEvent = new CustomEvent("keyMapKeydown", {
detail: { keyCode: event.keyCode },
bubbles: false,
cancelable: true
});
element.dispatchEvent(newEvent);
},
registered: false, // ensure we only listen to keydown once
restrict: 'A',
link: function(scope, element, attr) {
// register listener only if not already registered
if (!dir.registered) {
dir.registered = true;
angular.element(document).bind('keydown', dir.onKeydown);
}
var options = scope.$eval(attr.keyMap);
// listen for custom event which will be dispatched only to the
// element that has the 'focus' class
element.bind('keyMapKeydown', function(event) {
var keyCode = event.detail.keyCode;
if (options && (keyCode in options)) {
element.removeClass('focus');
angular.element(document.querySelector(options[keyCode])).addClass('focus');
event.stopPropagation();
}
});
}
};
You need to stop the propagation of events. Events propagate upwards. In your directive put something like the following:
$(elm).click(function (event) {
event.stopPropagation();
});
Or, you could create a stop-propagation directive itself. This SO question has a great way of doing it.

Categories

Resources