How to change focus in GridView on key navigation QML - image

I'm trying to change focus of an image while pressing keys (left, right, up and down) in GridView. When I press left, right, up or down key, I should change image focus and change the image when focus on that image is true. Otherwise, if focus is not on the image, old image should be seen.
Here is what I have by now:
And here is my code:
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 1920
height: 1080
visible: true
title: qsTr("Hello World")
Component.onCompleted: {
mojgrid.focus = true
}
function dobioResponseNapraviModel(response) {
console.log("dobioResponseNapraviModel", typeof response)
mojgrid.model=response
}
function request(){
console.log("BOK")
const xhr=new XMLHttpRequest()
const method="GET";
const url="http://api.themoviedb.org/4/list/1";
xhr.open(method, url, true);
xhr.setRequestHeader( "Authorization", 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI5YjBkOGVlMGQzODdiNjdhYTY0ZjAzZDllODM5MmViMyIsInN1YiI6IjU2MjlmNDBlYzNhMzY4MWI1ZTAwMTkxMyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.UxgW0dUhS62m41KjqEf35RWfpw4ghCbnSmSq4bsB32o');
xhr.onreadystatechange=function(){
if(xhr.readyState===XMLHttpRequest.DONE){
var status=xhr.status;
if(status===0 || (status>=200 && status<400)){
//the request has been completed successfully
// console.log(xhr.responseText.results)
dobioResponseNapraviModel(JSON.parse(xhr.responseText).results)
}else{
console.log("There has been an error with the request", status, JSON.stringify(xhr.responseText))
}
}
}
xhr.send();
}
/* function request(url, callback) {
var xhr=new XMLHttpRequest();
xhr.open("GET", url, true)
xhr.onreadystatechange = function() {
if(xhr.readyState===4) {
callback(xhr.responseText)
}
}
xhr.open("GET", url)
xhr.setRequestHeader( "Authorization", 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI5YjBkOGVlMGQzODdiNjdhYTY0ZjAzZDllODM5MmViMyIsInN1YiI6IjU2MjlmNDBlYzNhMzY4MWI1ZTAwMTkxMyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.UxgW0dUhS62m41KjqEf35RWfpw4ghCbnSmSq4bsB32o');
xhr.send()
}*/
GridView {
id:mojgrid
anchors.fill: parent
cellWidth: 250
cellHeight: 250
model:request()
currentIndex: modelData.id
keyNavigationEnabled: true
focus:true
Keys.onPressed:{
if((event.key === Qt.Key_Left) || (event.key===Qt.Key_Right) || (event.key===Qt.Key_Up) || (event.key===Qt.Key_Down)){
image.source="http://image.tmdb.org/t/p/w400"+modelData.poster_path
}
}
/* Keys.onUpPressed: {
request()
}*/
delegate: Rectangle{ id: rect; width: 350; height: 400; color:'gray';
Image{id:img; width:parent.width; height:parent.height-200
//fillMode: Image.PreserveAspectFit
//source:"http://image.tmdb.org/t/p/w400" + modelData.backdrop_path
source:focus?"http://image.tmdb.org/t/p/w400"+modelData.poster_path : "http://image.tmdb.org/t/p/w400" + modelData.backdrop_path
Rectangle{
id:rect2
width:parent.width
height:text.height
anchors.top:img.bottom
color:'black'
Text{
id:text
text:modelData.title
font.pointSize: 11
//anchors.top:image.bottom
elide:Text.ElideNone
color:'white'
}
}
MouseArea{
id:mouse
anchors.fill:parent
onClicked: {
parent.focus=true
}
}
}
Rectangle{
id:rect3
width:parent.width
height:200
anchors.top:rect.bottom
color:'red'
z:10
Text{
text:modelData.release_date
anchors.left:rect.left
anchors.top:rect.bottom
color: 'white'
}
}
}
}
}
I have Keys.onPressed here with an if condition, but it doesn't work. Can someone help me?

I simplified and reformat your code little bit but this code snippet is doing what do you want to do. When key navigation is enabled GridView is handling index update by itself. Actually key navigation is working and when you press keys current index is updated. GridView also handles limits on navigation, when you press down in the last row nothing happens as same as when you press left on the first column. The trick is using currentindex to update image.
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 1920
height: 1080
visible: true
title: qsTr("Hello World")
function dobioResponseNapraviModel(response) {
console.log("dobioResponseNapraviModel", typeof response)
mojgrid.model = response
}
GridView {
id: mojgrid
anchors.fill: parent
cellWidth: 250
cellHeight: 250
model: request()
keyNavigationEnabled: true
focus: true
delegate: Rectangle {
id: rect
width: 350
height: 400
color: 'gray'
property bool isCurrent: mojgrid.currentIndex === index
Image {
id: img
width: parent.width
height: parent.height - 200
source: isCurrent ? "http://image.tmdb.org/t/p/w400"
+ modelData.poster_path : "http://image.tmdb.org/t/p/w400"
+ modelData.backdrop_path
Rectangle {
id: rect2
width: parent.width
height: text.height
anchors.top: img.bottom
color: 'black'
Text {
id: text
text: modelData.title
font.pointSize: 11
//anchors.top:image.bottom
elide: Text.ElideNone
color: 'white'
}
}
MouseArea {
id: mouse
anchors.fill: parent
onClicked: {
mojgrid.currentIndex = index
}
}
}
}
}
function request() {
console.log("BOK")
const xhr = new XMLHttpRequest()
const method = "GET"
const url = "http://api.themoviedb.org/4/list/1"
xhr.open(method, url, true)
xhr.setRequestHeader(
"Authorization",
'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI5YjBkOGVlMGQzODdiNjdhYTY0ZjAzZDllODM5MmViMyIsInN1YiI6IjU2MjlmNDBlYzNhMzY4MWI1ZTAwMTkxMyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.UxgW0dUhS62m41KjqEf35RWfpw4ghCbnSmSq4bsB32o')
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
var status = xhr.status
if (status === 0 || (status >= 200 && status < 400)) {
dobioResponseNapraviModel(JSON.parse(
xhr.responseText).results)
} else {
console.log("There has been an error with the request",
status, JSON.stringify(xhr.responseText))
}
}
}
xhr.send()
}
}

Related

How to get mouse click position in qml Image component?

I tried to get the mouse click position in qml Image component, but what I got is not the real pixel-based image position, how can I get the pixel-based position of the image?
this is my qml code
Image {
id: sourceImage
width: parent.width
height: parent.height
fillMode: Image.PreserveAspectFit
source: "D://test.png"
mipmap: true
smooth: true
antialiasing: true
MouseArea {
width: parent.width
height: parent.height
focus: true
anchors.fill: parent
onClicked: {
print("clicked:", mouse.x,mouse.y)
}
}
}
the real image size is 3840*1260, but when I click the bottom-right position with the mouse, it prints clicked: 683 547
A lot of the code is boilerplate for debugging. The important part is the three functions mapToImage() and getXPosition()/getYPosition(). The latter is for getting the offset at which the image is drawn, when Image.PreservedAspectFit can't fill the Image and horizontalAlginment/verticalAlignment are used.
The map function uses sourceSize and paintedWidth/paintedHeight to get the scaling between the original size of the image and the actual drawn image. Keep in mind that when changing sourceSize and not letting the image set it, this method of getting the scaling might not work.
Just a note from the documentation:
sourceSize can be cleared to the natural size of the image by setting
sourceSize to undefined.
import QtQuick
import QtQuick.Controls
Window {
id: root
visible: true
width: 800
height: 600
title: qsTr("Image Picking")
function getXPosition(image : Image) : real {
switch (image.horizontalAlignment) {
case Image.AlignLeft:
return 0
case Image.AlignRight:
return image.width - image.paintedWidth
case Image.AlignHCenter:
default:
return (image.width - image.paintedWidth) * 0.5
}
}
function getYPosition(image : Image) : real {
switch (image.verticalAlignment) {
case Image.AlignTop:
return 0
case Image.AlignBottom:
return image.height - image.paintedHeight
case Image.AlignVCenter:
default:
return (image.height - image.paintedHeight) * 0.5
}
}
function mapToImage(mouse : MouseEvent, image : Image) {
root.xScale = image.paintedWidth / image.sourceSize.width
root.yScale = image.paintedHeight / image.sourceSize.height
root.xImgPosition = Math.floor((mouse.x - root.getXPosition(image)) / root.xScale)
root.yImgPosition = Math.floor((mouse.y - root.getYPosition(image)) / root.yScale)
}
property real xScale: 0
property real yScale: 0
property real xImgPosition: 0
property real yImgPosition: 0
Image {
id: image
anchors.centerIn: parent
width: 320
height: 240
fillMode: Image.PreserveAspectFit
//horizontalAlignment: Image.AlignLeft
source: "https://picsum.photos/id/17/200/300"
mipmap: true
smooth: true
antialiasing: true
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onPositionChanged: function(mouse) { root.mapToImage(mouse, image) }
}
Rectangle {
anchors.fill: parent
color: "transparent"
border {
width: 1
color: "gray"
}
}
// Debug rectangle showing the real dimension of the image before clipping by the fillMode
Rectangle {
x: root.getXPosition(image)
y: root.getYPosition(image)
width: image.paintedWidth
height: image.paintedHeight
color: "transparent"
border {
width: 1
color: "red"
}
}
}
Rectangle {
width: column.width + 40
height: column.height + 40
color: Qt.rgba(0.3, 0.3, 0.3, 0.4)
Column {
id: column
x: 20
y: 20
spacing: 4
ComboBox {
width: 180
textRole: "text"
valueRole: "value"
onActivated: image.fillMode = currentValue
Component.onCompleted: currentIndex = indexOfValue(image.fillMode)
model: [
{ value: Image.Stretch, text: qsTr("Stretch") },
{ value: Image.PreserveAspectFit, text: qsTr("Preserve Aspect Fit") },
{ value: Image.PreserveAspectCrop, text: qsTr("Preserve Aspect Crop") }
]
}
Text { text: "Mouse: " + mouseArea.mouseX + ", " + mouseArea.mouseY }
Text { text: "Image: " + image.width + ", " + image.height }
Text { text: "Painted: " + image.paintedWidth + ", " + image.paintedHeight }
Text { text: "Source: " + image.sourceSize.width + ", " + image.sourceSize.height }
Text { text: "Scaling: " + root.xScale + ", " + root.yScale }
Text { text: "Position: " + root.xImgPosition + ", " + root.yImgPosition }
}
}
}

Nuxt SSR return loaded image dimensions to server

I'm trying to preview a profile photo on an existing img element my problem is that the new image dimension become undefined outside of the img load function.
How can i pass these dimensions to the server so that i can properly resize the img element?
I've tried using Vuex Store as well to pass the dimensions but with the same undefined results.
I also have a function that listens for resize and after a user changes the window the img is resized properly, however i'm trying to do this without the event trigger. Even when i try to manually trigger the resize event with jQuery it does not resize. I'm under the impression that somehow the dimension of the new img source are not being set properly until a resize even refreshes the dimensions?
<b-img id="profilePhoto" v-bind="profile" :src="this.photo" class="profilePhoto" #change="handleResize()"></b-img>
export default {
data() {
return {
errors:{},
profile: {},
fileDimensions: {},
photo: '',
form: this.$vform({
id: '',
name: '',
email: '',
password: '',
role: '',
bio: '',
photo: ''
})
}
}
}
getPhoto(e) {
let file = e.target.files[0];
if (typeof file !== 'undefined'){
let reader = new FileReader()
let limit = 1024 * 1024 * 2
if (file.size > limit) {
return false;
}
reader.onloadend = (file) => {
this.form.photo = reader.result
this.photo = this.form.photo
}
reader.readAsDataURL(file)
$("<img/>",{
load : function(){
// will return dimensions fine if i use alert here
this.fileDimensions = { width:this.width, height:this.height} ;
},
src : window.URL.createObjectURL(file)
});
// becomes undefined outside of the load functions
var aw = this.fileDimensions.width
var ah = this.fileDimensions.height
var ph = $('.profile').height()
var pw = $('.profile').width()
console.log(this.fileDimensions.width)
if (ah>aw){
this.profile = { width: ph, height: 'auto'}
} else if (aw>ah) {
this.profile = { width: 'auto', height: ph}
} else {
this.profile = { width: ph+10, height: pw+10}
}
}
}
I expect to get the dimensions so i can determine how to set the width and height properties for the img element with its new src however the dimension become undefined.
I figured it out through another post. I had to create a promise. async await in image loading
getDimensions(src){
return new Promise((resolve,reject) => {
let img = new Image()
img.onload = () => resolve({ height: img.height, width: img.width })
img.onerror = reject
img.src = src
})
},
getPhoto(e) {
let file = e.target.files[0];
if (typeof file !== 'undefined'){
let reader = new FileReader()
let limit = 1024 * 1024 * 2
if (file.size > limit) {
return false;
}
reader.onloadend = (file) => {
this.form.photo = reader.result
this.photo = this.form.photo
}
reader.readAsDataURL(file)
this.getDimensions(URL.createObjectURL(file))
.then((dimensions) => {
if (process.client){
var ah = $('.profile').height()
var aw = $('.profile').width()
var ph = dimensions.height
var pw = dimensions.width
if (ph>pw){
this.profile = { width: ah+10, height: 'auto'}
} else if (pw>ph) {
this.profile = { width: 'auto', height: ah+10}
} else {
this.profile = { width: ah+10, height: aw+10}
}
}
})
}
}

Phaser 3.17 doesn't setect collision between tilemap layer and player sprite

No collisions between map layer and player sprite. But collisions between world bounds work. What is wrong?
I tried different workarounds that could find online and none of them worked.
Game config
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: "#f",
physics: {
default: 'arcade',
arcade: {
gravity: { y: gameState.gravity },
debug: true
}
},
scene: {
preload,
create,
update
}
};
Code in create() regarding the tilemap and its layers and the character
gameState.map = this.add.tilemap('map');
gameState.dungeonTileset = gameState.map.addTilesetImage('dungeon', 'dungeonTiles');
gameState.backgroundLayer = gameState.map.createStaticLayer('Background', gameState.dungeonTileset);
gameState.mapLayer = gameState.map.createStaticLayer('Map', gameState.dungeonTileset);
gameState.miscLayer = gameState.map.createStaticLayer('Misc', gameState.dungeonTileset);
gameState.mapLayer.setCollisionByExclusion([-1]);
this.physics.world.bounds.width = gameState.mapLayer.width;
this.physics.world.bounds.height = gameState.mapLayer.height;
gameState.player = this.physics.add.sprite(73, 398, 'player', 0);
gameState.player.setCollideWorldBounds(true);
this.physics.add.collider(gameState.player, gameState.mapLayer);
No warning and no errors are coming up in the console. I don't know what to do anymore.
Thanks in advance!
I have addited a little bit the original example so you can see how it looks, I think the problem in your code is the line concerning gameState.mapLayer.setCollisionByExclusion([-1]); but am not sure because I can't see how the tilemap is created
var config = {
type: Phaser.WEBGL,
width: 800,
height: 576,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
loader: {
baseURL: 'https://labs.phaser.io',
crossOrigin: 'anonymous'
},
pixelArt: true,
physics: {
default: 'arcade',
arcade: { gravity: { y: 300 } }
},
scene: {
preload: preload,
create: create,
update: update
}
};
var game = new Phaser.Game(config);
var map;
var cursors;
var player;
var groundLayer;
function preload ()
{
this.load.image('ground_1x1', 'assets/tilemaps/tiles/ground_1x1.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/tile-collision-test.json');
this.load.image('player', 'assets/sprites/phaser-dude.png');
}
function create ()
{
map = this.make.tilemap({ key: 'map' });
var groundTiles = map.addTilesetImage('ground_1x1');
map.createDynamicLayer('Background Layer', groundTiles, 0, 0);
groundLayer = map.createDynamicLayer('Ground Layer', groundTiles, 0, 0);
groundLayer.setCollisionBetween(1, 25);//here
player = this.physics.add.sprite(80, 70, 'player')
.setBounce(0.1);
this.physics.add.collider(player, groundLayer);
cursors = this.input.keyboard.createCursorKeys();
this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
this.cameras.main.startFollow(player);
}
function update ()
{
player.body.setVelocityX(0);
if (cursors.left.isDown)
{
player.body.setVelocityX(-200);
}
else if (cursors.right.isDown)
{
player.body.setVelocityX(200);
}
if (cursors.up.isDown && player.body.onFloor())
{
player.body.setVelocityY(-300);
}
}
<script src="//cdn.jsdelivr.net/npm/phaser#3.17.0/dist/phaser.min.js"></script>

react native and parse, currentuser is null after login and cmd+R

I'm having a problem with React Native and Parse JS SDK.
And I'm using ParseReact
I have built a login, sign up and a main view, Sign up and log in works well but after i logged in -> directed to main view and when I refresh the app (CMD+R) in my simulator, it brings me back to the login view again, i should be brought to Main view.
As you can see I have set a state for initialComponent:
this.state = {
InitialComponent : ((!currentUser) ? LoginView : MainView)
};
This allows my navigator to check for currentUser is null then load LoginView as initial component, else set Main View(user logged in)
'use strict';
var React = require('react-native');
var MainView = require('./MainView');
var LoginView = require('./LoginView');
var Parse = require('parse').Parse;
var ParseReact = require('parse-react');
Parse.initialize("mykey", "mykey");
var {
AppRegistry,
StyleSheet,
Text,
View,
TextInput,
TouchableHighlight,
Navigator,
Component
} = React;
class MyApp extends Component {
constructor(props) {
super(props);
var currentUser = Parse.User.current();
console.log('Current User:' + currentUser);
this.state = {
InitialComponent : ((!currentUser) ? LoginView : MainView)
};
}
render() {
return (
<Navigator
initialRoute={{
name : 'StatusList',
component: this.state.InitialComponent
}}
configureScene = {() =>{
return Navigator.SceneConfigs.FloatFromRight;
}}
renderScene={(route, navigator) =>{
if(route.component) {
return React.createElement(route.component, {navigator});
}
}}/>
);
}
}
AppRegistry.registerComponent('MyApp', function() { return MyApp });
In my Xcode console, i kept getting current user is null after each refresh even though i have previously logged in. On my parse app, I can see new session has been created.
In my LoginView.
'use strict';
var React = require('react-native');
var SignUp = require('./SignUp');
var MainView = require('./MainView');
var {
AppRegistry,
StyleSheet,
Text,
View,
TextInput,
TouchableHighlight,
Navigator,
AlertIOS,
Component
} = React;
var styles = StyleSheet.create({
container : {
flex: 1,
padding: 15,
marginTop: 30,
backgroundColor: '#0179D5',
},
text: {
color: '#000000',
fontSize: 30,
margin: 100
},
headingText: {
color: '#fff',
fontSize: 40,
fontWeight: '100',
alignSelf: 'center',
marginBottom: 20,
letterSpacing: 3
},
textBox: {
color: 'white',
backgroundColor: '#4BB0FC',
borderRadius: 5,
borderColor: 'transparent',
padding:10,
height:40,
borderWidth: 1,
marginBottom: 15,
},
greenBtn: {
height: 36,
padding: 10,
borderRadius: 5,
backgroundColor: '#2EA927',
justifyContent: 'center'
},
signUpButton: {
marginTop: 10,
height: 36,
padding: 10,
borderRadius: 5,
backgroundColor: '#FF5500',
justifyContent: 'center'
},
btnText: {
color : '#fff',
fontSize: 15,
alignSelf: 'center'
},
buttonText: {
fontSize: 18,
color: 'white',
alignSelf: 'center'
},
loginForm : {
flex:1,
marginTop:100
}
});
class LoginView extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
}
checkLogin() {
var success = true;
var state = this.state;
for(var key in state){
if(state[key].length <= 0){
success = false;
}
}
if(success) {
this._doLogin();
} else {
//show alert
AlertIOS.alert('Error','Please complete all fields',
[{text: 'Okay', onPress: () => console.log('')}]
);
}
}
goMainView() {
this.props.navigator.push({
title: "Home",
component: MainView
});
}
goSignUp() {
this.props.navigator.push({
title: "Sign Up",
component: SignUp
});
}
_doLogin() {
var parent = this;
Parse.User.logIn(this.state.username, this.state.password, {
success: function(user) {
parent.goMainView();
},
error: function(user, error) {
AlertIOS.alert('Login Error', error.message,
[{text: 'Okay', onPress: () => console.log('')}]
);
}
});
}
onUsernameChanged(event) {
this.setState({ username : event.nativeEvent.text });
}
onPasswordChanged(event) {
this.setState({ password : event.nativeEvent.text });
}
render() {
return(
<View style={styles.container}>
<View style={styles.loginForm}>
<Text style={styles.headingText}>
MyStatus
</Text>
<TextInput style={styles.textBox}
placeholder='Username'
onChange={this.onUsernameChanged.bind(this)}
placeholderTextColor='#fff'
autoCorrect={false}
>
</TextInput>
<TextInput style={styles.textBox}
placeholder='Password'
onChange={this.onPasswordChanged.bind(this)}
placeholderTextColor='#fff'
password={true}
>
</TextInput>
<TouchableHighlight style={styles.greenBtn}
underlayColor='#33B02C'
onPress={this.checkLogin.bind(this)}>
<Text style={styles.btnText}>Login</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.signUpButton}
underlayColor='#D54700'
onPress={this.goSignUp.bind(this)}>
<Text style={styles.btnText}>Sign Up</Text>
</TouchableHighlight>
</View>
</View>
);
}
}
module.exports = LoginView;
Am I doing it the wrong way? Kindly advice. Or is it something wrong with parse localstorage/session?
Because React Native only provides asynchronous storage, we're forced to make Parse.User.current() an asynchronous call that returns a Promise. Since you're already using Parse+React, it's really easy to handle this. Your component that changes based upon whether the user is logged in or not (MyApp) should subscribe to ParseReact.currentUser. This stays synchronized with the current user, and allows your component to automatically update the moment the user logs in or out. For a demo of this, look at the AnyBudget demo in the GitHub repo:
In react-native...
import Parse from 'parse/react-native';
Parse.User.currentAsync()
.then((currentUser)=>{
if (currentUser) {
Alert.alert('', JSON.stringify(currentUser))
}
});
At first in my case I use ParseReact.Mutation that work perfectly.
After that I got a requirement that some field need to be unique, so I use Parse.Cloud to solve problem.
// For normally situaltion is work fine.
ParseReact.Mutation.Set(this.data.myObject, {
normal_field: this.state.value
}).dispatch();
// But if I use Parse.Cloud. Is there any solution to sync data to ParseReact.currentUser?
Parse.Cloud.run('setUniqueField', {
userID: this.data.user.id.objectId,
uniqueField: this.state.value,
}, {
success: function (response) {
// It doesn't work!
// ParseReact.currentUser.update();
this.props.navigator.pop();
}.bind(this),
error: function (error) {
console.log('[Parse Cloud Error]: ', error);
}
});
#Andrew's solution (alone) didn't work for me. In case anyone else is stuck, here's what was happening: subscribing to Parse.User.current() didn't work, and this.data.user was always null.
To fix this, I had to change:
var Parse = require('parse').Parse;
var ParseReact = require('parse-react');
to
var Parse = require('parse/react-native').Parse;
var ParseReact = require('parse-react/react-native');
then everything started working beautifully. It was loading the browser version of the parse modules until I forced it to load the react-native versions.

Kendo UI Slider / how to disable keyboard input?

Is there a way to disable the keyboard events on Kendo UI Slider? Basically, I want to prevent changing the value of the slider when pressing left and right arrow keys. Is this possible at all?
Please note that slider is being dynamically inserted into the DOM as part of a KO custom binding handler.
ko.bindingHandlers.tone = {
init: function(element, valueAccessor) {
if (valueAccessor().settingToneEnabled) {
var $el = $(element);
var tag = '<span class="dropdown mrgn-tp-md"><ul class="dropdown-menu dropdown-menu-right text-center pddng-sm" aria-labelledby="tonedropdownMenu"><li class="pddng-lft-md pddng-rght-sm"><span id="tone-slider" title="tone"></span></li><li class="pddng-rght-sm"><i class="icon icon-delete"></i> ' + i18n['ps-deleteArticleToneLabel'] + '</li></ul></span>';
$(tag).appendTo($el);
var $slider = $('#tone-slider', $el);
var $delLink = $('a.del', $el);
var $dropdown = $('span.dropdown', $el);
$('a.dropdown-toggle', $dropdown).on('click', function() {
$('.dropdown-menu', $dropdown).toggle();
});
$slider.kendoSlider({
change: function(e) {
var va = valueAccessor();
va.value(e.value);
if ($.isFunction(va.handleUserInput)) {
va.handleUserInput();
}
},
showButtons: false,
min: -1,
max: 1,
smallStep: 1,
value: valueAccessor().value() || 0,
tickPlacement: 'none',
tooltip: {
enabled: false
}
});
$('.k-draghandle', $el).off('keydown');
$delLink.on('click', function(e) {
e.preventDefault();
if ($delLink.attr('disabled')) {
return;
}
var va = valueAccessor();
va.value(null);
if ($.isFunction(va.handleUserInput)) {
va.handleUserInput();
}
});
$el.data('slider', $slider.data("kendoSlider"));
$el.data('deleteButton', $delLink);
$el.data('dropdown', $dropdown);
} else {
$('<span href="" data-tone></span>').appendTo(element);
}
},
update: function(element, valueAccessor) {
var toneValues = {
'1': {
name: i18n['ps-tonePositive'],
val: 1,
css: 'icon-tone-positive'
},
'0': {
name: i18n['ps-toneNeutral'],
val: 0,
css: 'icon-tone-neutral'
},
'-1': {
name: i18n['ps-toneNegative'],
val: 0,
css: 'icon-tone-negative'
},
};
var $tone = $('*[data-tone]', element);
var val = valueAccessor().value() || 0;
var tone = toneValues[val.toString()] || toneValues['0'];
$tone.removeClass()
.addClass('icon').addClass(tone.css)
.attr('title', tone.name);
if (valueAccessor().settingToneEnabled) {
$('#tone-slider', element).data("kendoSlider").value(val);
}
},
};
You can try to remove the keydown handler.
See demo.

Resources