Limit jQuery Mobile slider to responding to press-hold-drag - jquery-mobile

On iPad Safari (and desktop Safari and Chrome), I need to have horizontal sliders on a page that scrolls vertically, where the sliders can't accidentally be moved. Unfortunately, jQuery mobile sliders do respond to (imperfect) vertical swipes on iPad.
A nice way to fix this is to set up the sliders so that the only way to move the knob is to press-hold and then drag. Here's what I've hacked together (note: this only works on touch interfaces):
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css">
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<style>
div.input-container {
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
</style>
</head>
<body>
<div id="top">
<div>
<h1>Sliders for iPad</h1>
</div>
<div>
<label for="test1">Test:</label>
<div class="input-container">
<input type="range" name="test1" value="50" min="0" max="100" disabled>
</div>
</div>
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<div>
<label for="test2">Test:</label>
<div class="input-container">
<input type="range" name="test2" value="50" min="0" max="100" disabled>
</div>
</div>
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<div>
<label for="test3">Test:</label>
<div class="input-container">
<input type="range" name="test3" value="50" min="0" max="100" disabled>
</div>
</div>
</div>
<script>
$(function() {
$(".input-container").addClass("disable-drag")
.on("taphold", tapholdHandler)
.on('touchmove', moveHandler)
.on('touchend', endHandler)
;
function moveHandler(event) {
var containingDiv = $(".input-container");
if (!containingDiv.hasClass('disable-drag')) {
///
console.log(event);
$('a').offset({left: event.originalEvent.targetTouches[0].clientX});
var left = 68;///parseInt($('.ui-slider-track')[0].css('margin-left'));
var w = event.originalEvent.target.offsetWidth - left;
var percent = ((event.originalEvent.targetTouches[0].clientX - left) / w) * 100;
$('input').val(percent).slider('refresh');
///
}
}
function tapholdHandler(event) {
console.log(event)
var containingDiv = $(".input-container");
if (containingDiv.hasClass('disable-drag')) {
containingDiv.removeClass("disable-drag");
event.preventDefault();
event.stopPropagation();
$('input').slider('enable').slider('refresh');
}
}
function endHandler(event) {
$('input').slider('disable').slider('refresh');
$(".input-container").addClass("disable-drag")
}
});
</script>
</body>
</html>
The slider is disabled until a press-hold is detected, at which time it springs to life, updates the knob position and value while the user drags, and returns to disabled when touch ends. It kind of works, but is too brittle and I don't want to be doing essentially the same calcs that the slider already does. Between the /// markers what I'd really like is to programmatically click at the current mouse location so that the knob moves to that spot - without interrupting the press-hold-drag gesture. Is this possible? Here's what I tried but it doesn't work:
///
$(".ui-slider-track").trigger('click'); //todo: narrow the selector to the target slider
///
and
///
$(document.elementFromPoint(event.originalEvent.targetTouches[0].clientX, event.originalEvent.targetTouches[0].clientY)).click();
///
...or is there some other mobile UI library with sliders that don't respond to vertical swipes?

Ok, I figured out a fairly clean simple solution. Tested on iPad Safari. It also keeps the text field enabled so it can be edited directly.
<script>
// The following manages the sliders so that vertical swiping (scrolling) never inadvertently changes a slider value
$(function() {
var timerId;
$.event.special.tap.tapholdThreshold = 250; // default is 750, but that seems too long for this scenario
$(".input-container")
.on('taphold', tapholdHandler)
.on('touchmove', moveHandler)
.on('touchend', endHandler)
;
$('.input-container input')
.prop('disabled', false).removeClass('ui-state-disabled') // allow the user to edit the displayed value
.on('change', function() {
$(this).slider('refresh');
$(this).prop('disabled', false).removeClass('ui-state-disabled'); // override the above line's disabling of the text field
$(this).blur();
})
;
function tapholdHandler(event) {
$(event.currentTarget).find('input').slider('enable').slider('refresh');
}
function moveHandler(event) {
if (timerId)
clearTimeout(timerId); // as long as the user is interacting with the slider, don't revert it to disabled
$(document.elementFromPoint(event.originalEvent.targetTouches[0].clientX, event.originalEvent.targetTouches[0].clientY)).trigger('vmousedown');
}
function endHandler(event) {
$(document.elementFromPoint(event.originalEvent.changedTouches[0].clientX, event.originalEvent.changedTouches[0].clientY)).trigger('vmousedown').trigger('vmouseup'); // the purpose of this is to move the slider knob even if the user's touch didn't move
timerId = setTimeout(function() { // give the above induced event time to run the associated handler
$(event.currentTarget).find('input').slider('disable').slider('refresh');
$(event.currentTarget).find('input').prop('disabled', false).removeClass('ui-state-disabled'); // allow the user to edit the displayed value
}, 2000);
}
});
</script>

Related

when submit button is click the input data has been disappear how can I rectify?

when submit button is clicked the input data is disappear in html How can I rectify the problem?
<html>
<head>
<title>hhhh</title>
</head>
<body>
<form id="form">
<input type="text" id="username" placeholder="username" />
<input type="submit" id="btn" />
</form>
</body>
<script>
var a = document.getElementById("username");
var b = document.getElementById("btn");
b.addEventListener("click", () => {
console.log(a.value);
});
</script>
</html>

Render html form into main html page using AngularJS app method

I am very new to AngularJS and trying to understand how AngularJS can use along with ASP.NET-MVC5 application. In my first attempt I want to run AngularJS app from basic HTML page (in my case index.html) where app holding form template in html format, also I have add global variable, controller, service via factory and directives but I cannot manage to run this app 'employee-form' inside index.html. In order to test if angularJS is initialize and working properly, I have added very basic angularjs code inside in html and it works.. I am not sure where I have done mistake
AngularFormsApp.js (global variable)
var angularFormsApp = angular.module('angularFormsApp', []);
efController.js
angularFormsApp.controller('efController',
function efController($scope, efService) {
$scope.employee = efService.employee;
});
efService.js
angularFormsApp.factory('efService',
function () {
return {
employee: {
fullName: "Khurram Zahid",
notes: "The ideal employee, just don't mess with him",
department: "IT Development",
perkCar: true,
perkStock: false,
perkSixWeeks: true,
payrollType: "none"
}
}
});
efDirective.js
angularFormsApp.directive('employeeForm',
function () {
return {
restrict: 'E', //E stands for element, meaning we want to use this directive as element
templateUrl: '~/App/EmployeeForm/efTemplate.html'
}
});
efTemplate.html (form)
<div class="form-group">
<label for="fullName">Name</label>
<input type="text" id="fullName" name="fullName" class="form-control" />
</div>
<div class="form-group">
<label for="notes">Notes</label>
<input type="text" id="notes" name="notes" class="form-control" />
</div>
<div class="form-group">
<label for="department">Department</label>
<select id="department" name="department" class="form-control">
<option>Engineering</option>
<option>Marketing</option>
<option>Finance</option>
<option>IT Development</option>
</select>
</div>
<br/>
<span><b>Perks</b></span>
<div class="checkbox">
<label><input type="checkbox" value="perCar"/>Company Car</label>
</div>
<div class="checkbox">
<label><input type="checkbox" value="perkStock" />perk Stock</label>
</div>
<div class="checkbox">
<label><input type="checkbox" value="perkSixWeeks" />perk Six Weeks</label>
</div>
<input type="submit" value="Submit Form" />
index.html
<!DOCTYPE html>
<html>
<head >
<title>Angular JS</title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<script src="Scripts/angular.min.js"></script>
<script src="App/AngularFormsApp.js"></script>
<script src="App/EmployeeForm/efController.js"></script>
<script src="App/EmployeeForm/efService.js"></script>
<script src="App/EmployeeForm/efDirective.js"></script>
</head>
<body ng-app="angularFormsApp">
<div class="AngularJSTestBlockCode">
<div>
<input type="text" ng-model="name" />
<br />
<h1>Hello {{name}}</h1>
</div>
<br /><br />
<div>
{{458/8}}
</div>
</div>
<div>-------------------------------------------------------</div> <br/><br/>
<div ng-controller="efController">
<employee-form>????????????????????
</div>
You need a route provider to render your html page. Here is your example
.config(['$stateProvider',function($stateProvider) {
$stateProvider.state('dashboard', {
url:'/dashboard',
templateUrl: 'views/dashboard/main.html',
})
.state('dashboard.create-example',{
templateUrl:'views/example/create.html',
url:'/create-example',
controller:'Ctrl'
})
then in your controller(efController.js) put this $state.transitionTo('dashboard.create-example'); to render your page to any html you want

jQuery UI - Unable to Trigger Spinstop on Spinner

I'm having trouble triggering the "spinstop" event I have set for a jQuery UI spinner
I have created a number of spinner elements that update the sum total text box at the bottom on a stop: event. I also have a "Reset" button that will reset all the values back to 0.
Clicking on the "Reset" button will reset the values in the elements, but will not trigger the stop: event to reset the values.
I have tried changing the spinner event to spin: or change: with the same result (actually, change: doesn't have the behaviour I wanted).
Below is an example code.
HTML:
<input type="text" class="number" /><br />
<input type="text" class="number" /><br />
<input type="text" class="number" /><br />
<input type="text" class="number" /><br />
<input type="text" id="total" /><br />
<button id="reset">Reset</button>
jQuery:
$.fn.sum = function () {
var sum = 0;
this.each(function () {
sum += 1 * ($(this).val());
});
return sum;
};
$(".number").spinner({
stop: function () {
$("#total").val($(".number").sum());
}
}).val(0);
$("#total").val($(".number").sum());
$("#reset").click(function () {
$(".number").val(0).trigger("spinstop");
});
What am I doing wrong?
JSFIDDLE

JQueryValidation with MVC 4 not validating on blur

I am beating my head on the wall for hours with MVC 4 and jQuery validation to validate the first first on blur. I have tried attaching the validation to the entire form AND to the individual element (first field) to no avail. If I add an alert() into the blur event it seems to fire but no validation of the required field. I have additional validations to add after the required is working but haven't gotten to them yet. I don't know that it is a problem with the MVC 4. JQueryvalidate is v1.10. I have also tried setting up the validator and then calling .valid() on the element I want validated using the .blur and still not validation that I can see.
$(function () {
$('#productionOrder').focus();
$.validator.addMethod("cMinLength", $.validator.methods.minlength,
$.format("Must contain as least {0} chars"));
$.validator.addClassRules("productionOrder", { cMnLength: 3 });
$('#myForm').validate({
onkeyup: false,
//onfocusout: false,
errorClass: 'fieldError'
//rules: {
// productionOrder: "required number",
// tc: "required",
// dn: "required"
//}
});
$("#towCount").bind("change keyup", function () {
$form.validate().element("#towCount");
});
//$('#productionOrder').validate({
// //onkeyup: false,
// onfocusout: false,
// errorClass: 'fieldError',
// rules: {
// productionOrder: {
// required: true
// }
// }
//});
});
And the .cshtml
#model FiberLine2.ViewModels.Creel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<style>
.fieldError {
border-color: red;
border-width: medium;
}
.input-label {
font-size: 13px;
width: 130px;
height: 30px;
display: inline-block;
}
</style>
</head>
<body>
<form id="myForm">
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div>
<!-- app header -->
<label>#Resources.Strings.User: </label>
<label>#User.Identity.Name</label>
</div>
<fieldset>
<legend>#Resources.Strings.Creel #Resources.Strings.Load</legend>
<div>
<div id="errorDiv"></div>
<hr />
#Html.Label(#Resources.Strings.ProductionOrder, new { #class = "input-label lock" })
<input type="text" id="productionOrder" name="productionOrder" class="required" maxlength="4" />
<br />
<label class="input-label lock">#Resources.Strings.Tow #Resources.Strings.Count</label>
<input type="text" id="towCount" name="tc" class="required" size="5" maxlength="5" value="299" />
<br />
<label class="input-label lock">#Resources.Strings.Batch #Resources.Strings.Sequence</label>
<input type="text" id="doffNumber" name="dn" size="5" maxlength="5" value="1" />
<br />
<label class="input-label">#Resources.Strings.Creel #Resources.Strings.Position</label>
<input type="text" id="creelPosition" name="cp" size="5" maxlength="5" />
<br />
<label class="input-label">#Resources.Strings.Batch #Resources.Strings.ID</label>
<input type="text" id="creelNumber" name="cn" size="7" maxlength="7" />
<br />
<hr />
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
</form>
</body>
</html>
Can you try this instead?
var settngs = $.data($('#myForm')[0], 'validator').settings;
settngs.onkeyup = false;

jQuery mobile radio list with data-type="horizontal" fails in dynamic form

Here is an example HTML page that demonstrates the issue:
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.css" />
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.js"></script>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>My Title</h1>
</div><!-- /header -->
<div data-role="content" id="cp">
<form id="form">
<div data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal" data-mini="true">
<legend>Test 1:</legend>
<input type="radio" name="r1" id="r1a" value="none" checked="checked" /><label for="r1a">A</label>
<input type="radio" name="r1" id="r1b" value="detail"/><label for="r1b">B</label>
<input type="radio" name="r1" id="r1c" value="measure"/><label for="r1c">C</label>
</fieldset>
</div>
</form>
</div><!-- /content -->
</div><!-- /page -->
<script type="text/javascript">
$(document).ready(function() {
var form = $('#form');
form.append('<div data-role="fieldcontain">');
form.append(' <fieldset data-role="controlgroup" data-type="horizontal">');
form.append(' <legend>Test 2:</legend>');
form.append(' <input type="radio" name="r2" id="r2a" value="none" checked="checked" /><label for="r2a">A</label>');
form.append(' <input type="radio" name="r2" id="r2b" value="detail"/><label for="r2b">B</label>');
form.append(' <input type="radio" name="r2" id="r2c" value="measure"/><label for="r2c">C</label>');
form.append(' </fieldset>');
form.append('</div');
form.trigger('create');
});
</script>
</body>
</html>
Save this page and load it in a borwser. You will see that the "Test 1" radio list comes up horizontal (as it should because of the data-type="horizontal" attribute). However the "Test 2" radio list, which is added dynamically, comes up vertically, which is the default setting. It seems the data-type="horizontal" has no effect on the dynamically created radio list.
Is there a refresh or event anyone knows about which I should trigger somewhere in the DOM to get this to work?
The problem is the way you are adding your new elements to the form. If you change your javascript function to this you'll see that it works:
$(document).ready(function() {
var form = $('#form');
var newElement = '';
newElement += '<div data-role="fieldcontain" data-type="horizontal">';
newElement += ' <fieldset data-role="controlgroup" data-type="horizontal">';
newElement += ' <legend>Test 3:</legend>';
newElement += ' <input type="radio" name="r3" id="r3a" value="none" checked="checked" /><label for="r3a">A</label>';
newElement += ' <input type="radio" name="r3" id="r3b" value="detail"/><label for="r3b">B</label>';
newElement += ' <input type="radio" name="r3" id="r3c" value="measure"/><label for="r3c">C</label>';
newElement += ' </fieldset>';
newElement += '</div>';
form.append(newElement);
form.trigger('create');
});
Think about it this way: Each time the append() function is used the browser attempts to add whatever you've given it to the DOM. But because you have broken your elements across different calls to append() the browser has to try to make sense of it. So when you have this:
form.append('<div data-role="fieldcontain">');
The browser sees that you've left off a closing div tag and tries to fix it for you by adding it. This means your next call to append() will not go inside the div you just added but after it because the browser has automatically closed it for you.
You should add complete, well-formed elements to avoid this issue.

Resources