I want select some text highlights with Greasemonkey.When I see that four radio button, Greasemonkey i need highlights my option.
Example: I want auto select label RealMadrid.
<div class="row">
<input type="radio" tabindex="3" value="answer1" name="ctl00$ContentPlaceHolder1$1" id="ContentPlaceHolder1_answer1"><label for="ContentPlaceHolder1_answer1">Bayern</label></div>
<div class="row">
<input type="radio" tabindex="4" value="answer2" name="ctl00$ContentPlaceHolder1$1" id="ContentPlaceHolder1_answer2"><label for="ContentPlaceHolder1_answer2">Barcelona</label></div>
<div class="row">
<input type="radio" tabindex="5" value="answer3" name="ctl00$ContentPlaceHolder1$1" id="ContentPlaceHolder1_answer3"><label for="ContentPlaceHolder1_answer3">RealMadrid</label></div>
<div class="row">
<input type="radio" tabindex="6" value="answer4" name="ctl00$ContentPlaceHolder1$1" id="ContentPlaceHolder1_answer4"><label for="ContentPlaceHolder1_answer4">Lyon</label></div>
</div>
Greasemonkey code: (it's checked radio , but instead i need highlight text)
is it possible ?
var labels = document.getElementsByTagName('label'); //get the labels
for (var i = 0; i < labels.length; ++i) { //loop through the labels
if (labels[i].textContent == "RealMadrid") { //check label text
labels[i].click(); //if correct text, click the label
}
}
Javascript:
var radioButtons = document.querySelectorAll('input[type=radio]');
for(var i = 0; i < radioButtons.length; i++) {
radioButtons[i].addEventListener('change', changeHandler, false);
}
function changeHandler(event) {
var b = event.target;
if(b.checked) {
document.querySelector('label[for=' + b.id + ']').style.background = 'yellow';
var notB = document.querySelectorAll('label:not([for=' + b.id + '])');
for(var j = 0; j < notB.length; j++) {
notB[j].style.background = '';
}
}
}
jQuery:
$(':radio').change(function() {
if($(this).is(':checked')) {
$(this).next().css('background', 'yellow');
$(':radio').not(this).next().css('background', '');
}
});
Demo
Related
I have an issue where on updating a cell with cellEdited, The page jumps back to the top of the page when the mutator or formatter is called.
I've tried setting table.redraw(false) and then the formatter/mutator doesn't seem to do anything.
When a user updates the proficiency level the formatter or mutator should add a button if it's above 3. It works perfectly. However it jumps to the top of the screen.
Any help appreciated.
var evidenceMutator = function(value, data, type, params, component){
skillsTable.redraw(false);
var claimedProficiency = data.Proficiency;
var skillClaimed = data.SkillID;
var Evidence = data.Evidence;
var memberID = $("#user").data("memberid");
if (claimedProficiency >= 3 ) {
// has provided evidence
if (Evidence == 1) {
return '<a class="btn btn-outline-success btn-xs btn-slim evidence" href="#" id="'+ skillClaimed + '" onclick="openEvidenceModal(this, this.id, '+ memberID +')"> <i class="fas fa-check-circle cssover"></i> Edit Evidence </a>';
} else { // needs to provide
return '<a class="btn btn-outline-danger btn-xs btn-slim evidence" href="#" id="'+ skillClaimed + '" onclick="openEvidenceModal(this, this.id, '+ memberID +')"> <i class="fas fa-times-circle cssover"></i> Add Evidence </a>';
}
} else {
// cell.getElement().style.color = "#CCD1D1";
//cell.getElement().style.fontStyle ="italic";
// cell.getElement().style.fontSize = "0.75em";
return ' No Evidence Needed';
}
}
function complianceTick(cell) {
var isCompliant = cell.getData().Compliance;
var Evidence = cell.getData().Evidence;
var claimedProficiency = cell.getData().Proficiency;
// style all with sucesss and only change if we need to
cell.getElement().style.color = "#33CC66";
cell.getElement().style.fontSize = "0.85em";
cell.getElement().style.fontStyle = "italic";
if (claimedProficiency >= 3 ) {
if (Evidence == '1') {
return '<i class="fas fa-check-circle"></i>';
} else {
cell.getElement().style.color = "#FF0000";
cell.getElement().style.fontSize = "0.85em";
cell.getElement().style.fontWeight = "bold";
return '<i class="fas fa-times-circle"></i>';
}
} else {
return '';
}
}
var skillsTable = new Tabulator("#SkillsTable", {
index: "SkillID",
height:"100%",
headerVisible:false,
autoResize:true,
layout:"fitColumns", //fit columns to width of table
groupBy:"SkillCatID",
groupHeader: groupMaker,
initialSort:[ //set the initial sort order of the data
{column:"RowOrder", dir:"asc"}
],
columns:[ //define the table columns
{title:"", field:"SkillID", visible:false},
{title:"Skill", field:"SkillName", visible:true, headerSort:false, formatter: skillName},
{title:"", field:"SkillCatID", visible:false},
{title:"", field:"SkillCatName", visible:false},
{title:"My Level", field:"Proficiency", visible:true, editor:inputEditor, formatter:prof, width:"7%", headerSort:false, align:"center",
cellEdited:function(cell, row, success){ // EDITING FUNCTION
var $value = cell.getValue();
var $field = cell.getField();
var $row = cell.getRow();
var $id = $row.getData().SkillID;
var integer = parseInt($value, 10);
if ($value != "" && integer < 5 && integer >= 0) {
// update record
updateRecord($id, $field, $value, $row);
//$row.update({"Proficiency" : $value});
//$row.update({"Evidencer" : $value});
skillsTable.updateRow($id, {id:$id,"Proficiency":$value});
skillsTable.updateRow($id, {id:$id,"Evidencer":$value});
} else {
cell.restoreOldValue();
if ($value != "") {
alert ("Values should be between 0 and 4, the cell has been restored to its previous value.")
}
}
},
},
{title:"Target", field:"MinLevel", visible:false, headerSort:false},
{title:"", field:"Proficiency", visible:true, formatter: skillDec, headerSort:false},
{title:"Evidence", field:"Evidencer", visible:true, hozAlign:"center", formatter: evidenceCell, mutator: evidenceMutator, width:"10.5%", headerSort:false},
{title:"", field:"RowOrder", visible:false, sorter:"number"},
{title:"disc", field:"DisciplineID", visible:false, headerFilter:true}
],
});
UPDATE
I think I've narrowed down the issue to the formatter:
```
function evidenceCell(cell, formatterParms, onRendered) {
var claimedProficiency = cell.getData().Proficiency;
var skillClaimed = cell.getData().SkillID;
var Evidence = cell.getData().Evidence;
var memberID = $("#user").data("memberid");
if (claimedProficiency >= 3 ) {
// has provided evidence
if (Evidence == 1) {
return '<a class="btn btn-outline-success btn-xs btn-slim evidence" href="#" id="'+ skillClaimed + '" onclick="openEvidenceModal(this, this.id, '+ memberID +')"> <i class="fas fa-check-circle cssover"></i> Edit Evidence </a>';
} else { // needs to provide
return '<a class="btn btn-outline-danger btn-xs btn-slim evidence" href="#" id="'+ skillClaimed + '" onclick="openEvidenceModal(this, this.id, '+ memberID +')"> <i class="fas fa-times-circle cssover"></i> Add Evidence </a>';
}
} else {
cell.getElement().style.color = "#CCD1D1";
cell.getElement().style.fontStyle ="italic";
cell.getElement().style.fontSize = "0.75em";
return 'No Evidence Needed';
}
}
```
It looks like the issue is with the cell.getData(). It seems to trigger the scroll to the top of page. I think it may be a bug with the newer version. Testing 4.2 and it seems to not be an issue. However, I have issues with modals going to the top of the page with the older version.
The issue seems to be with the virtual DOM. In my case I can luckily turn it off by using the following:
virtualDom:false,
I'm not sure this would be a good fix for people with hundreds of rows.
My _loadMoreRows and _isRowLoaded are not getting called, so loadedRowsMap remains empty and I am unable to identify the rows loaded to avoid making HTTP request .
Here's my complete code :
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {formatDate} from '../../helper/date';
import { recentActivitiAction } from '../actions/dashboardAction';
import { BeatLoader } from 'react-spinners';
import {AutoSizer, List, CellMeasurer, InfiniteLoader, CellMeasurerCache} from 'react-virtualized';
import styles from '../../css/AutoSizer.module.css';
import Skeleton from 'react-skeleton-loader';
const STATUS_LOADING = 1;
const STATUS_LOADED = 2;
const mapStateToProps = (state) => {
return {
recentActList: state.dashboardReducer.recentActList,
activitiLoading: state.dashboardReducer.activitiLoading
}
}
const mapDispatchToProps = (dispatch) => {
return {
getRecentActivites: (postData, callback) => {
dispatch(recentActivitiAction(postData, callback));
}
};
}
class RecentActivitiComp extends Component {
constructor(props) {
super(props);
this.state = {
loadedRowCount: 0,
loadedRowsMap: {},
loadingRowCount: 0,
};
this.cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: 100
});
this._timeoutIdMap = {};
this._isRowLoaded = this._isRowLoaded.bind(this);
this._loadMoreRows = this._loadMoreRows.bind(this);
this.renderRow = this.renderRow.bind(this);
this.onRowsRendered = this.onRowsRendered.bind(this);
this.noRowsRenderer = this.noRowsRenderer.bind(this);
}
componentWillUnmount() {
Object.keys(this._timeoutIdMap).forEach(timeoutId => {
clearTimeout(timeoutId);
});
}
componentDidMount() {
var postData = {
"userName": "admin",
"queryType": "GET_RECENT_PROJECTS",
"data": {
pageStart: 1,
pageEnd: 20
}
};
this.props.getRecentActivites(postData, this.recentActResponse.bind(this));
}
updateDimensions() {
this.cache.clearAll();
this.activitiList.recomputeRowHeights();
}
recentActResponse(response) {
if (response.status === "FAILED") {
// handle error
}
}
_fieldGenerator(row, index) {
var formattedDate = formatDate(row.lastModified),
output = '', JSX = '';
if(formattedDate) {
formattedDate = formattedDate.split('-');
output = (
<div className="project-info-value byline">
<span>{formattedDate[0]}<sup>{formattedDate[1]}</sup> {formattedDate[2]} {formattedDate[3]}</span> by <a>{row.modifiedBy}</a>
</div>
)
} else {
output = (
<div className="project-info-value byline">
<span>Invalid Date by </span> <a>{row.modifiedBy}</a>
</div>
)
}
if(row.action === "upcoming-release") {
JSX =
<li key={index}>
<div className="block">
<div className="block_content">
<h2 className="title">{row.action}</h2>
{output}
<p className="excerpt">{row.notes}<a> Read More</a></p>
</div>
</div>
</li>
} else if(row.action === "created") {
JSX =
<li key={index}>
<div className="block">
<div className="block_content">
<h2 className="title">{row.type} <a>{row.name}</a> {row.action}</h2>
{output}
<p className="excerpt"></p>
</div>
</div>
</li>
} else if(row.action === "modified") {
JSX =
<li key={index}>
<div className="block">
<div className="block_content">
<h2 className="title">{row.type} <a>{row.name}</a> {row.action}</h2>
{output}
<p className="excerpt"></p>
</div>
</div>
</li>
} else {
JSX =
<li key={index}>
<div className="block">
<div className="block_content">
<h2 className="title"><a>{row.person}</a> added to <a>{row.addedTo}</a></h2>
{output}
<p className="excerpt"></p>
</div>
</div>
</li>
}
return JSX;
}
renderRow({ index, key, style, parent }) {
var JSX = '', content = '';
const list = this.props.recentActList
const {loadedRowsMap} = this.state;
if (loadedRowsMap[index] === STATUS_LOADED) {
const row = list[index];
JSX = this._fieldGenerator(row, index);
content = (
JSX
);
} else {
content = (
<div className={styles.placeholder} style={{width: 480}} />
);
}
return (
<CellMeasurer
cache={this.cache}
columnIndex={0}
key={key}
parent={parent}
rowIndex={index}
>
{({ measure }) => (
<div key={key} style={{...style}} onLoad={measure}>
{content}
</div>
)}
</CellMeasurer>
);
}
_isRowLoaded({index}) {
const {loadedRowsMap} = this.state;
return !!loadedRowsMap[index]; // STATUS_LOADING or STATUS_LOADED
}
_loadMoreRows({startIndex, stopIndex}) {
const {loadedRowsMap, loadingRowCount} = this.state;
const increment = stopIndex - startIndex + 1;
for (var i = startIndex; i <= stopIndex; i++) {
loadedRowsMap[i] = STATUS_LOADING;
}
this.setState({
loadingRowCount: loadingRowCount + increment,
});
const timeoutId = setTimeout(() => {
const {loadedRowCount, loadingRowCount} = this.state;
delete this._timeoutIdMap[timeoutId];
for (var i = startIndex; i <= stopIndex; i++) {
loadedRowsMap[i] = STATUS_LOADED;
}
this.setState({
loadingRowCount: loadingRowCount - increment,
loadedRowCount: loadedRowCount + increment,
});
promiseResolver();
}, 1000 + Math.round(Math.random() * 2000));
this._timeoutIdMap[timeoutId] = true;
let promiseResolver;
return new Promise(resolve => {
promiseResolver = resolve;
});
}
noRowsRenderer() {
return <div className={styles.noRows}>No rows</div>;
}
onRowsRendered({overscanStartIndex, overscanStopIndex, startIndex, stopIndex}) {
const list = this.props.recentActList.length ? this.props.recentActList : [];
const {loadedRowsMap} = this.state;
console.log(startIndex, stopIndex, this.state.loadedRowCount);
// if(startIndex + 10 === list.length && this._isRowLoaded(startIndex) !== STATUS_LOADED) {
// var postData = {
// "userName": "admin",
// "queryType": "GET_RECENT_PROJECTS",
// "data": {
// pageStart: 1,
// pageEnd: 10
// }
// };
// this.props.getRecentActivites(postData, this.recentActResponse.bind(this));
// }
}
render() {
const list = this.props.recentActList.length ? this.props.recentActList : [];
const {loadedRowCount, loadingRowCount} = this.state;
return (
<div className="recent left_panel">
<div className="x_panel">
<div className="x_title sub_title">
<h2>Recent Activites</h2>
</div>
<div className="x_content">
<div className="dashboard-widget-content">
<ul className="list-unstyled timeline widget">
<InfiniteLoader
isRowLoaded={this._isRowLoaded}
loadMoreRows={this._loadMoreRows}
rowCount={list.length}>
{({onRowsRendered, registerChild}) => (
<div className={styles.list}>
<AutoSizer onResize={this.updateDimensions.bind(this)}>
{({width, height}) => (
<List
ref={(ref) => {
this.activitiList = ref;
registerChild(ref);
}}
noRowsRenderer={this.noRowsRenderer}
onRowsRendered={this.onRowsRendered}
deferredMeasurementCache={this.cache}
width={width}
height={height}
deferredMeasurementCache={this.cache}
rowHeight={this.cache.rowHeight}
rowRenderer={this.renderRow}
rowCount={list.length} /* Initially render 20 records */
/>
)}
</AutoSizer>
</div>
)}
</InfiniteLoader>
</ul>
{/* <div className="align-right">
<a href="http://karthik.jivox.com/studio/eam/production/index.php#"
className="btn-jivox-1">
<span className="btn-icon">
<i className="fas fa-chevron-down" aria-hidden="true"></i>
</span> Show More Activities
</a>
</div> */}
</div>
</div>
</div>
</div>
);
}
}
const RecentActiviti = connect(mapStateToProps, mapDispatchToProps)(RecentActivitiComp);
export default RecentActiviti;
As you can see I am making API call at didMount phase and therefore populating my redux store with the data. Data is coming fine. But isRowLoaded and loadMoreRows are not getting called.
I have debugged the sample code of infiniteLoader.example.js, there during the inital render those two functions are called and properly set loadedRowsMap.
What I am doing wrong here ? :-( Any help would be greatly appreciated .
I have resolved the issue after making some changes.
const mapStateToProps = (state) => {
return {
myList: state.dashboardReducer.myList
}
}
const list = this.props.myList.length ? this.props.recentActList : [];
const rowCount = list.length + (moreToBeLoaded ? 1 : 0);
To know why 1 more row loaded pls check this post react-virtualized InfiniteLoader/List - working example using AJAX
So the issue in my code was I was writing my custom onRowsRendered function and it was not handling the response correctly. Now I changed the code to use the one passed by InfiniteLoader.
Hope that helps.
<InfiniteLoader
isRowLoaded={this._isRowLoaded}
loadMoreRows={this._loadMoreRows}
rowCount={rowCount}>
{({onRowsRendered, registerChild}) => (
<div className={styles.list}>
<AutoSizer onResize={this.updateDimensions.bind(this)}>
{({width, height}) => (
<ActiviitiList
ref={(ref) => {
this.activitiList = ref;
registerChild(ref);
}}
width={width}
height={height}
onRowsRendered={onRowsRendered}
rowCount={rowCount}
rowHeight={this.cache.rowHeight}
rowRenderer={this._rowRenderer}
overscanRowCount={3}
deferredMeasurementCache={this.cache}
/>
)}
</AutoSizer>
</div>
)}
</InfiniteLoader>
(The code you've posted has a lot going on; you'll probably get better responses if you remove the parts that aren't related to your question.)
My advice is to take a look at the values you're getting for list.length, which you're passing to InfiniteLoader's rowCount prop. InfiniteLoader will only call loadMoreRows if rowCount is higher than the number of rows it has data for.
For example: during the first render, the value is 0, because you have not fetched any data yet. This prevents a call to loadMoreRows during the first render.
I also noticed that you are keeping loadedRowCount and loadingRowCount in state, but you never use them for anything. I don't think that's related to your issue, but it's also probably not intentional.
i'm using Swiper and want custom pagination. This question was answered here, but i misunderstood, how to make that pagination clickable, nothing worked. What am i doing wrong?
$(document).ready(function () {
var mySwiper = new Swiper('.swiper-container', {
nextButton: '.swiper-button-next'
, prevButton: '.swiper-button-prev'
, pagination: '.swiper-pagination'
, paginationClickable: true
, paginationHide: false
, paginationType: 'custom'
, paginationElement: 'div'
, paginationCustomRender: function (swiper, current, total) {
var names = [];
$(".swiper-wrapper .swiper-slide").each(function (i) {
names.push($(this).data("name"));
});
var text = "";
for (let i = 1; i <= total; i++) {
if (current == i) {
text += "<div class='swiper-pagination-container swiper-pagination-container-active'><div class='swiper-pagination-icon swiper-pagination-icon-active'></div><div>" + names[i] + "</div></div>";
}
else {
text += "<div class='swiper-pagination-container'><div class='swiper-pagination-icon'></div><div>" + names[i] + "</div></div>";
}
}
return text;
}
});
$(".swiper-pagination-container").on("click", function () {
mySwiper.slideTo($(".swiper-pagination-container").index(this) + 1);
});
}
The difference is that i placed .swiper-pagination div outside the .swiper-wrapper:
<div class="swiper-pagination"></div>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide" data-name="7 сентября">Slide 1</div>
<div class="swiper-slide" data-name="10 декабря">Slide 2</div>
<div class="swiper-slide" data-name="14-23 декабря">Slide 3</div>
<div class="swiper-slide" data-name="30 декабря">Slide 4</div>
<div class="swiper-slide" data-name="5-6 февраля">Slide 5</div>
<div class="swiper-slide" data-name="8 февраля">Slide 6</div>
<div class="swiper-slide" data-name="9 февраля">Slide 7</div>
</div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
It's simple, try it:
window.mainSlider = new Swiper('.swiper-container', {
nextButton: '.swiper-button-next'
, prevButton: '.swiper-button-prev'
, pagination: '.swiper-pagination'
, paginationClickable: true
, paginationHide: false
paginationBulletRender : function (index, className) {
var slide = $('.' + this.wrapperClass).find('[data-name]')[index],
label = $(slide).attr('data-name');
return '<span class="' + className + '">' + (typeof label !== 'undefined' ? name : '') + '</span>';
}
});
I tried this, it works on swiper with loop set to true, if loop set to false, simply remove +1 from the index will do.
pagination: {
el: $('.your_class').find('.swiper-pagination'),// to find the swiper-pagination you put outside of the swiper-container
clickable: true,
renderBullet: function (index, className) {
var slider_array = [];
var el = $('.swiper-container')
el.find('[data-name]').each(function () {
slider_array.push($(this).data('name'));
});
console.log(slider_array);
return '<span class="' + className + '">' + slider_array[index + 1] + '</span>';
}
}
I have a doubt.
I have a main.jsp that includes another 2 jsp and a submit button. Both of them are part of a form.
The second one includes an auto field with a validator:
<div id="groupwork-fields" >
<div class="lfr-form-row lfr-form-row-inline">
<div class="row-fields">
<aui:input fieldParam='name' id="repetibleName" cssClass="full-size"
name="<%=AwardConstants.FIELD_OTHERS_NAME%>"
label='<%=AwardConstants.LABEL_NAME %>'
value="">
<aui:validator name="custom" errorMessage="fill-name">
function (val, fieldNode, ruleValue) {
var result = true;
var selector = document.getElementById("<portlet:namespace/>select-group").value;
if (selector == 1 && val === "") {
result = false;
}
return result;
}
</aui:validator>
</aui:input>
<aui:input cssClass="full-size"
id="email0" fieldParam='email0'
name="email0"
label='<%=AwardConstants.LABEL_EMAIL %>'
value="">
<aui:validator name="maxLength">100</aui:validator>
<aui:validator name="email"></aui:validator>
<aui:validator name="custom" errorMessage="fill-email">
function (val, fieldNode, ruleValue) {
var result = true;
var name = document.getElementById("<portlet:namespace/>name0").value;
if (name !== "" && val === "") {
result = false;
}
return result;
}
</aui:validator>
</aui:input>
</div>
</div>
</div>
After validating those fields and pressing the submit button goes to the next method:
public void saveAutofieldData(ActionRequest actionRequest, ActionResponse actionResponse) throws PortalException, SystemException {
String groupworkIndexes = actionRequest.getParameter("groupworkIndexes");
_log.info("::::::::::::::::groupworkIndexes:::::::::::::::::::::::" + groupworkIndexes);
/**
* Split the row index by comma
*/
String[] indexOfRows = groupworkIndexes.split(",");
_log.info("::::::::::::::::indexOfRows.length:::::::::::::::::::::::"+ indexOfRows.length);
for (int i = 0; i < indexOfRows.length; i++) {
String name = (actionRequest.getParameter("name"+ indexOfRows[i])).trim();
String email = (actionRequest.getParameter("email"+ indexOfRows[i])).trim();
_log.info("::::::::::::Name::::::::::::::" + name);
_log.info("::::::::::::Email::::::::::::::" + email);
}
}
The problem is when It tries to read: actionRequest.getParameter("groupworkIndexes"); I get null.
Thank you in advance
I finally got the solution.
All examples I've seen it have been with "actionRequest" to retrieve the data:
String groupworkIndexes = actionRequest.getParameter("groupworkIndexes");
String name = actionRequest.getParameter("name" + indexOfRows[i]));
But in my case i've used the following lines:
String name = (uploadPortletRequest.getParameter("name" + indexOfRows[i]));
String groupworkIndexes = (uploadPortletRequest.getParameter("groupworkIndexes"));
Not always we would get the prefered values with actionRequest
Is there any Semantic UI Numeric Up Down control with minimum, maximum and step count options ?
We can use type as 'number' to get the required increment/decrement control.
<Input type="number" />
Not found such control so I made this code:
HTML
<div class="ui right labeled input">
<input type="text" id="txtNum" value="5">
<div class="ui mini vertical buttons">
<button class="ui icon button" command="Up"> <i class="up chevron icon"></i>
</button>
<button class="ui icon button" command="Down"> <i class="down chevron icon"></i>
</button>
</div>
</div>
JS
// Constants
var KEY_UP = 38,
KEY_DOWN = 40;
// Variables
var min = 0,
max = 30,
step = 1;
$('.ui.icon.button').click(function () {
var command = $(this).attr('command');
HandleUpDown(command);
});
$('#txtNum').keypress(function (e) {
var code = e.keyCode;
if (code != KEY_UP && code != KEY_DOWN) return;
var command = code == KEY_UP ? 'Up' : code == KEY_DOWN ? 'Down' : '';
HandleUpDown(command);
});
function HandleUpDown(command) {
var val = $('#txtNum').val().trim();
var num = val !== '' ? parseInt(val) : 0;
switch (command) {
case 'Up':
if (num < max) num += step;
break;
case 'Down':
if (num > min) num -= step;
break;
}
$('#txtNum').val(num);
}
Here is the DEMO.