I wonth to be able to uncheck radio button on second click with custom design radio buttons.
Here is HTML code:
<input type="radio" id="sortForm11" name="sortForm11" value="descPrice"/>
<label for="sortForm11">Text<span ></span></label>
Here is CSS code:
input[type="radio"] {
display:none;
}
input[type="radio"] + label span {
display:inline-block;
width: 20px;
height: 20px;
margin: 0 10px 0 0;
vertical-align:middle;
background:url(../images/checkbox.png) left top no-repeat;
background-size: 20px 20px;
cursor:pointer;
border-radius: 2px;
float:right;
}
input[type="radio"]:checked + label span {
background-color: #4bc2ff;
}
Here is js code:
$('input[name=sortForm11]').on('click',function () {
var $radio = $(this);
// if this was previously checked
if ($radio.data('waschecked') == true)
{
console.log('cao');
$radio.prop('checked', false);
$radio.data('waschecked', false);
}
else
$radio.data('waschecked', true);
// remove was checked from other radios
$radio.siblings('input[name=sortForm11]').data('waschecked', false);
});
P.S. : If my input field is visible and if I test this it is working but if I tweak it for custom design it doesn't work.
You can use this example:
https://jsfiddle.net/k0sp350f/5/
$('input[name=sortForm11] + label span').on('click', function (e) {
var $radio = $(this).parent().prev();
// if this was previously checked
if ($radio.is(':checked')) {
$radio.removeAttr('checked');
} else {
$('input[name=' + $radio.attr('name') + ']').removeAttr('checked');
$radio.attr('checked', 'checked');
}
});
Unchecking it works too!
UPDATED: For multiple radio buttons with the same name
<input type="radio" id="sortForm11" name="sortForm11" value="descPrice"/>
<label for="sortForm11">Text<span ></span></label>
<br>
<input type="radio" id="sortForm11" name="sortForm12" value="descPrice"/>
<label for="sortForm12">Text2<span ></span></label>
var val = 0;
var val2 = 0;
$('input[name=sortForm11]').on("click", function(){
console.log(val);
if($(this).val()==val)
{$(this).prop('checked', false);
val = -1;
}
else val = $(this).val();
});
var val2 = 0;
$('input[name=sortForm12]').on("click", function(){
console.log(val2);
if($(this).val()==val2)
{$(this).prop('checked', false);
val2 = -1;
}
else val2 = $(this).val();
});
Use the following code.
var val = 0;
$('input[name=sortForm11]').on("click", function(){
console.log(val);
if($(this).val()==val)
{$(this).prop('checked', false);
val = -1;
}
else val = $(this).val();
});
Here is example : http://jsfiddle.net/wuAWn/534/
Related
I am working on a autocomplete feature and to populate in on a list currently the list is just showing the results but I can't select them to add it to the input element.
Here is a sample of the code:
var search_terms = ['a', 'b', 'c'];
function autocompleteMatch(input) {
if (input == '') {
return [];
}
var reg = new RegExp(input);
return search_terms.filter(function(term) {
if (term.match(reg)) {
return term;
}
});
}
function showResults(val) {
res = document.getElementById("result");
res.innerHTML = '';
let list = '';
let terms = autocompleteMatch(val);
for (i = 0; i < terms.length; i++) {
list += '<li>' + terms[i] + '</li>';
}
res.innerHTML = '<ul>' + list + '</ul>';
}
<input type="text" class="form-control" placeholder="Explain in fewer words with the primary product key word (Eg: OneDrive sync issue, etc.)" name="post" required id="id_post" onKeyUp="showResults(this.value)">
<span class="fas fa-asterisk" style="font-size:12px;color:red;position:absolute; right:20px;top:12px;" id="asterix"></span>
<div id="result"></div>
Any advice to add the elements on list to the input. I've search for similar suggestions but I couldn't apply the answers to my code.
Edit: In my case the solutions posted here were not working because the calling of the script
<script type="text/javascript" src="app.js" charset="utf-8"></script>
was at the top. So it was failing with a Uncaught TypeError: Cannot read property 'addEventListener' of null. After moving <script> section to the end of the <body> suggested answers started to work.
Is this how it should work. I added an event listener to res that tests id a <li> was clicked. If so, the innerHTML of the <li> is inserted as value in the <input>. Using the dispatchEvent() I update the list as if it was a keyup event.
var search_terms = ['abc', 'abcde', 'abde'];
var res = document.getElementById("result");
var id_post = document.getElementById("id_post");
function autocompleteMatch(input) {
if (input == '') {
return [];
}
var reg = new RegExp(input)
return search_terms.filter(function(term) {
if (term.match(reg)) {
return term;
}
});
}
function showResults(val) {
let terms = autocompleteMatch(val);
list = terms.map(term => `<li>${term}</li>`).join('');
res.innerHTML = '<ul>' + list + '</ul>';
}
res.addEventListener('click', e => {
if(e.target.nodeName == "LI"){
id_post.value = e.target.innerHTML;
id_post.dispatchEvent(new Event('keyup'));
}
});
<input type="text" class="form-control" placeholder="Explain in fewer words with the primary product key word (Eg: OneDrive sync issue, etc.)" name="post" required id="id_post" onKeyUp="showResults(this.value)">
<div id="result"></div>
Considering your original code there are some missing details like autocomplete function and keyboard events (up/down/enter).
1) HTML
// form (autocomplete off) disables autocomplete integration with external tools like 1password
<form autocomplete="off">
<div class="autocomplete" id="autocomplete-container">
<input id="autocomplete-input" type="text" placeholder="Type Something...">
</div>
<input type="submit">
</form>
2) List of possible options (to make it dynamic, load the list before binding it to the autocomplete method)
const data = ["Aaa", "Aab", "Aac", "Abc", "Bbc", "Bbd", "Xpto", "Item1", "Item2", "SomethingElse"];
3) Autocomplete Functionality
const autocomplete = (container, inputElement, list) => {
var currentFocus = -1;
inputElement.addEventListener('input', () => {
var autocompleteText = inputElement.value;
hideList();
if (!autocompleteText) {
return false;
}
const autocompleteList = document.createElement('div');
autocompleteList.setAttribute('id', 'autocomplete-list');
autocompleteList.setAttribute('class', 'autocomplete-items');
container.appendChild(autocompleteList);
list.forEach((item, index) => {
if (
item.substr(0, autocompleteText.length).toUpperCase() ===
autocompleteText.toUpperCase()
) {
const tempId = `hiddenInput_${index}`;
const text = item.substr(0, autocompleteText.length);
const autocompleteMatch = document.createElement('div');
autocompleteMatch.innerHTML = `<strong>${text}</strong>`;
autocompleteMatch.innerHTML += item.substr(autocompleteText.length);
autocompleteMatch.innerHTML += `<input type='hidden' id='${tempId}' value='${item}'>`;
autocompleteMatch.addEventListener('click', (event) => {
const clickedElement = event.target.getElementsByTagName('input')[0];
inputElement.value = clickedElement.value;
hideList();
});
autocompleteList.appendChild(autocompleteMatch);
}
});
});
inputElement.addEventListener('keydown', function (e) {
const autoCompleteList = document.getElementById('autocomplete-list');
var autoCompleteDiv;
if (autoCompleteList) {
autoCompleteDiv = autoCompleteList.getElementsByTagName('div');
}
if (e.keyCode === 40) {
// KEY DOWN
currentFocus++;
addActive(autoCompleteDiv);
} else if (e.keyCode === 38) {
// KEY UP
currentFocus--;
addActive(autoCompleteDiv);
} else if (e.keyCode === 13) {
// ENTER
e.preventDefault();
if (currentFocus > -1 && autoCompleteDiv) {
autoCompleteDiv[currentFocus].click();
}
}
});
const addActive = (item) => {
if (!item) {
return false;
}
removeActive(item);
if (currentFocus >= item.length) {
currentFocus = 0;
}
if (currentFocus < 0) {
currentFocus = item.length - 1;
}
item[currentFocus].classList.add('autocomplete-active');
};
const removeActive = (autoCompleteItems) => {
Array.from(autoCompleteItems).forEach((item) => {
item.classList.remove('autocomplete-active');
});
};
const hideList = (element) => {
var autoCompleteItems =
document.getElementsByClassName('autocomplete-items');
if (autoCompleteItems && autoCompleteItems.length > 0) {
Array.from(autoCompleteItems).forEach((item) => {
if (element !== item && element !== inputElement) {
item.parentNode.removeChild(item);
}
});
}
};
document.addEventListener('click', (event) => hideList(event.target));
};
// this part binds the autocomplete with the HTML
window.addEventListener('load', function () {
const container = document.getElementById('autocomplete-container');
const inputElement = document.getElementById('autocomplete-input');
autocomplete(container, inputElement, data);
});
CSS
* { box-sizing: border-box; }
body {
font: 16px Arial;
}
.autocomplete {
display: inline-block;
position: relative;
width: 300px;
}
input {
border: 1px solid transparent;
background-color: #f1f1f1;
padding: 10px;
font-size: 16px;
}
input[type=text] {
background-color: #f1f1f1;
width: 100%;
}
input[type=submit] {
background-color: DodgerBlue;
color: #fff;
}
.autocomplete-items {
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
border-top: none;
z-index: 99;
top: 100%;
left: 0;
right: 0;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
background-color: #e9e9e9;
}
.autocomplete-active {
background-color: DodgerBlue !important;
color: #ffffff;
}
Based on W3School - How TO - Autocomplete
Live Version - Codesandbox
Try This Code
var searchTerms = ["OneDrive sync issue", "Abcde", "123456"];
var result = document.getElementById("result");
rul = document.createElement("ul");
result.appendChild(rul);
rul.classList.add("datalist");
for(var x = 0; x < searchTerms.length; x++ ){
rli = document.createElement("li");
rul.appendChild(rli);
rli.innerHTML = searchTerms[x];
rli.classList.add("d-none");
rli.addEventListener("click", function(){
document.getElementById("id_post").value = this.innerHTML;
this.classList.add("d-none");
});
}
function showResults(v){
var ListItems = rul.querySelectorAll("li");
for(var i = 0; i < ListItems.length; i++){
var c = ListItems[i].innerHTML.toLowerCase();
v = v.toLowerCase();
if(c.indexOf(v) > -1 && v !== ""){
ListItems[i].classList.remove("d-none");
}
else{
ListItems[i].classList.add("d-none");
}
}
}
.d-none{ display:none; }
.datalist li{ cursor:pointer; }
<input
type="text"
class="form-control"
placeholder="Explain in fewer words with the primary product key word (Eg: OneDrive sync issue, etc.)"
name="post"
required
id="id_post"
onKeyUp="showResults(this.value)">
<span
class="fas fa-asterisk"
style="font-size:12px;color:red;position:absolute; right:20px;top:12px;"
id="asterix"></span>
<div id="result"></div>
I have two overlapping (100% overlapped) select dropdowns, I want to be able to click on the one overlapping the openable select drop down while triggering the other select dropdown to open up with the list of options. I have seen references this is unsupported and if so I need a workaround to get the option to preserver the value of the overlayed select while only opening the first select box z-index is less than the first select box.
How do I accomplish this requirement?
Fiddle
https://jsfiddle.net/0rgthvub/
HTML
<select class="long-select" style="background-color:white; position: absolute !important; width: 200px; z-index: 10 !important;" onmousedown="(function(event){processOpen(event);})(event, this)">
<option value="Open - some description" selected></option>
</select>
JavaScript/jQuery
function processOpen(e) {
e.preventDefault();
$input = $("select.shortened-select");
var $this = $(this);
if ($input.is("select") && !$('.lfClon').length) {
var $clon = $input.clone();
var getRules = function(e){ return {
position: 'absolute',
left: e.offset().left,
top: e.offset().top,
width: e.outerWidth(),
height: e.outerHeight(),
opacity: 0,
margin: 0,
padding: 0
};};
var rules = getRules($this);
$clon.css(rules);
$clon.on("mousedown.lf", function(){
debugger;
$clon.css({
marginLeft: $input.offset().left - rules.left,
marginTop: $input.offset().top - rules.top,
});
$clon.on('change blur', function(){
$input.val($clon.val()).show();
$clon.remove();
});
$clon.off('.lf');
});
$clon.on("mouseout.lf", function(){
$(this).remove();
});
$clon.prop({id:'',className:'lfClon'});
$clon.appendTo('body');
}
value = document.querySelectorAll(".shortened-select option")[document.querySelector(".shortened-select").selectedIndex].value;
$input.value = "value";
$input.value.show();
}
function focus() {
[].forEach.call(this.options, function(o) {
if (o.val === ""){
o.setAttribute('data-descr', document.querySelectorAll(".shortened-select option")[document.querySelector(".shortened-select").selectedIndex].getAttribute("val"));
o.selected = 'selected';
}
else
{
o.textContent = o.getAttribute('val');
}
});
}
function blur(e) {
[].forEach.call(this.options, function(o) {
o.textContent = o.getAttribute('val') + ' - ' + o.getAttribute('data-descr');
});
this.blur();
}
function mouseup(e) {
[].forEach.call(this.options, function(o) {
o.textContent = o.getAttribute('val') + ' - ' + o.getAttribute('data-descr');
});
}
[].forEach.call(document.querySelectorAll('.shortened-select'), function(s) {
s.addEventListener('focus', focus);
s.addEventListener('change', blur);
blur.call(s);
});
I have a element which has an integer count.
<span class="likes-count"> 2 </span>
And a div when clicked have to toggle the increment and decrement of the value.
<div class="liked"></div>
Problem:
I have called a function on $('.liked').clicked which increments the value and changes the class to .notliked
And another onclick function decrements the value, but it's not working properly.
Please review my code. I guess this is not the best way to do this.
Here's my demo code.
$(document).ready(function() {
$(".notliked").click(function() {
var $this = $(this);
$this.removeClass('notliked');
$this.addClass('liked')
$count = $('.likes-count');
$count.html((parseInt($count.html(),10) || 0) + 1);
});
$(".liked").click(function() {
var $this = $(this);
$this.removeClass('liked');
$this.addClass('notliked');
$count = $('.likes-count');
$count.html((parseInt($count.html(),10) || 0) - 1);
});
});
.heart {
color: #fff;
height:50px;
cursor:pointer;
width:50px;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span class="likes-count"> 2 </span>
<div class="liked heart">Click</div>
You need to delegate the click event. At the beginning $(".notliked") returns 0 elements and so it's never executed.
In order to increment/decrement the text value you can use:
.text( function ) like:
$count.text(function(idx, txt) {
// convert text to number and increment by one
return +txt + 1;
});
The snippet:
$(document).on('click', ".notliked", function() {
var $this = $(this);
$this.removeClass('notliked');
$this.addClass('liked')
$count = $('.likes-count');
$count.text(function(idx, txt) {
return +txt + 1;
});
});
$(document).on('click', ".liked", function() {
var $this = $(this);
$this.removeClass('liked');
$this.addClass('notliked');
$count = $('.likes-count');
$count.text(function(idx, txt) {
return (+txt == 0) ? 0 : (+txt - 1);
});
});
.heart {
color: #fff;
height:50px;
cursor:pointer;
width:50px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="likes-count"> 0 </span>
<div class="liked heart">Click</div>
I have the following code. When I press the down/up key, i can successfully select the different value but the focus is still on the main input box. I want to move focus to the selected element. That is if i press down key and if selected element is John Doe, then the focus should also be on John doe element and not on the input box.
I set the following 2 things in the code but they are not working
$selected.focus();
and
$current.focus();
What am I doing wrong ?
You can't just focus() a <li> element. From the docs:
The focus event is sent to an element when it gains focus. This event is implicitly applicable to a limited set of elements, such as form elements (<input>, <select>, etc.) and links (<a href>). In recent browser versions, the event can be extended to include all element types by explicitly setting the element's tabindex property. An element can gain focus via keyboard commands, such as the Tab key, or by mouse clicks on the element.
You can try setting the tabindex property.
LIVE DEMO
I have added a counter variable , and if counter > 1 then only key Up, Down, Enter method calls, also on Enter Hit again i am setting counter=0 so you get last selected Li. Instead of calling removeClass('selected') everytime, i am calling it only if my counter >1.
$(document).ready(function () {
var $listItems = $('li.autocomplete-list'),
$div = $('div.autofill'),
$input = $('#example');
$div.hide();
var allLI = $(".autocomplete .autocomplete-list");
var counter = 0;
$('input#example').on('keydown', function (e) {
var key = e.keyCode,
$selected = $listItems.filter('.selected'),
$current;
//console.log("Show");
$div.show();
counter++;
if (counter > 1) {
if (key == 40) { // Down key
$selected.focus();
if (!$selected.length || $selected.is(':last-child')) {
$current = $listItems.eq(0);
} else {
$current = $selected.next();
}
} else if (key == 38) { // Up key
if (!$selected.length || $selected.is(':first-child')) {
$current = $listItems.last();
} else {
$current = $selected.prev();
}
} else if (key == 13) {
var value = $selected.text().split('(')[0].trim();
$input.val(value);
$div.hide();
counter = 0;
}
if ($current) {
allLI.removeClass('selected');
$current.addClass('selected');
$current.focus();
}
}
});
$('li.autocomplete-list').on('click', function (e) {
var value = $(this).text().split('(')[0].trim();
$input.val(value);
$div.hide();
});
$('li.autocomplete-list').hover(
function () {
$(this).addClass('partial_selected')
},
function () {
$(this).removeClass('partial_selected')
});
});
You need to explicitly assign tabindex property for the list items if you want to focus on them. see http://jsfiddle.net/tkay/40ctx17s/1/ . But a downside to this is you will not be able to move further down in the list since input is not focused.
$(document).ready(function () {
var $listItems = $('li.autocomplete-list'),
$div = $('div.autofill'),
$input = $('#example');
$div.hide();
$('input#example').on('keydown', function (e) {
var key = e.keyCode,
$selected = $listItems.filter('.selected'),
$current;
$div.show();
$listItems.removeClass('selected');
if (key == 40) { // Down key
$selected.focus();
if (!$selected.length || $selected.is(':last-child')) {
$current = $listItems.eq(0);
} else {
$current = $selected.next();
}
} else if (key == 38) { // Up key
if (!$selected.length || $selected.is(':first-child')) {
$current = $listItems.last();
} else {
$current = $selected.prev();
}
} else if (key == 13) {
var value = $selected.text().split('(')[0].trim();
$input.val(value) ;
$div.hide();
}
if ($current) {
$current.addClass('selected');
$current.focus();
console.log($current);
}
});
$('li.autocomplete-list').on('click', function (e) {
var value = $(this).text().split('(')[0].trim();
$input.val(value);
$div.hide();
});
$('li.autocomplete-list').hover(
function(){ $(this).addClass('partial_selected') },
function(){ $(this).removeClass('partial_selected') }
);
});
.selected {
background: #a4a4a4;
}
.hover {
background: #A9D0F5;
}
ul {
padding: 5px 0;
}
li {
padding: 6px 3px;
}
.autofill {
width: 250px;
}
.input {
width: 250px;
height: 2.2em;
padding: .3em .5em;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<input type="text" class="input" name="example" id="example" placeholder="example..." autocomplete="off" list="examplelist" />
<div class="autofill">
<ul class="autocomplete">
<li class="autocomplete-list" tabindex="-1">John Doe (San Jose, CA)</li>
<li class="autocomplete-list" tabindex="-1">Jane Doe (San Francisco, CA)</li>
<li class="autocomplete-list" tabindex="-1">John Jane (San Carlos, CA)</li>
</ul>
</div>
Updated Answer after comments of OP
$(document).ready(function () {
var $listItems = $('li.autocomplete-list'),
$div = $('div.autofill'),
$input = $('#example');
$div.hide();
$('input#example').on('keydown', function (e) {
var key = e.keyCode,
$selected = $listItems.filter('.selected'),
$current;
$div.show();
$listItems.removeClass('selected');
if (key == 40) { // Down key
$selected.focus();
if (!$selected.length || $selected.is(':last-child')) {
$current = $listItems.eq(0);
} else {
$current = $selected.next();
}
} else if (key == 38) { // Up key
if (!$selected.length || $selected.is(':first-child')) {
$current = $listItems.last();
} else {
$current = $selected.prev();
}
} else if (key == 13) {
if ($selected.length){
e.preventDefault();
}
var value = $selected.text().split('(')[0].trim();
$input.val(value) ;
$div.hide();
}
if ($current) {
$current.addClass('selected');
}
});
$('li.autocomplete-list').on('click', function (e) {
var value = $(this).text().split('(')[0].trim();
$input.val(value);
$div.hide();
});
$('li.autocomplete-list').hover(
function(){ $(this).addClass('partial_selected') },
function(){ $(this).removeClass('partial_selected') }
);
$("#frm").submit(function(){
console.log('submitted');
});
});
.selected {
background: #a4a4a4;
}
.hover {
background: #A9D0F5;
}
ul {
padding: 5px 0;
}
li {
padding: 6px 3px;
}
.autofill {
width: 250px;
}
.input {
width: 250px;
height: 2.2em;
padding: .3em .5em;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<form id="frm">
<input type="text" class="input" name="example" id="example" placeholder="example..." autocomplete="off" list="examplelist" />
<input type="submit" value="Submit"/>
</form>
<div class="autofill">
<ul class="autocomplete">
<li class="autocomplete-list">John Doe (San Jose, CA)</li>
<li class="autocomplete-list">Jane Doe (San Francisco, CA)</li>
<li class="autocomplete-list">John Jane (San Carlos, CA)</li>
</ul>
</div>
How does citicards.com implement the login ID text box with special mask?
When you type "johndoe" and focus out the textbox becomes "jo***oe"
Is there a HTML5 mask with pattern?
Here is a sample implementation of the desired behaviour using pure javascript. This is just for a sample. You may need to do length check etc before actually using substr
document.querySelector("input#accountName").addEventListener("blur", function() {
var value = this.value;
document.querySelector("#maskedAccountName").textContent=this.value.substr(0,2)+this.value.substr(2,value.length-2).replace(/./g,"*")+this.value.substr(this.value.length-2, this.value.length);
this.style.display = "none";
document.querySelector("#maskedAccountName").style.display = "block";
}, false);
document.querySelector("#maskedAccountName").addEventListener("click", function() {
this.style.display = "none";
document.querySelector("input#accountName").style.display = "block";
document.querySelector("input#accountName").focus();
}, false);
div#maskedAccountName {
border: 1px solid rgba(231, 231, 231, 0.67);
padding: 2px;
display: none;
border-top-style: inset;
-webkit-appearance: textfield;
background-color: white;
width: 120px;
}
<input type="text" id="accountName">
<div id="maskedAccountName">
</div>
The reason why I'm not changing the existing input value is I may not be able to read the original value when accessed inside the form submit. So i've created a hidden div which is shown in place of the original input element. You can style the div to be same as the input element using CSS.
You have to use JS/jQuery. First count how mush letters from start and end you wish to take off, then replace everything else with * and append to fake input field.
You can see that in action here (replace opacity to 0 to completely hide input field, display: none will not work here, because you have to click on input itself):
$(document).ready(function() {
$("#hField").focusin(
function() {
$('#hFieldSp').text($(this).val());
});
$("#hField").focusout(function() {
var start = '';
var end = '';
var value = $(this).val();
var stars = '';
if (value.length < 3) {
return;
}
if (value.length > 6) {
start = value.substring(0, 2);
end = value.substring(value.length - 2);
stars = '*'.repeat(Math.max(1, value.length - 4));
} else {
start = value.substring(0, 1);
end = value.substring(value.length - 1);
stars = '*'.repeat(Math.max(1, value.length - 2));
}
$('#hFieldSp').text(start + stars + end);
});
$(document).on('input paste change', '#hField', function() {
$('#hFieldSp').text($(this).val());
});
});
String.prototype.repeat = function(num) {
return new Array(num + 1).join(this);
}
.wrapper {
float: left;
position: relative;
}
#hField,
#hFieldSp {
width: 100px;
height: 30px;
line-height: 30px;
border: 1px solid #ddd;
}
#hField {
opacity: .2;
position: absolute;
left: 0;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div id="hFieldSp"></div>
<input type="text" id="hField" />
</div>
I would use a dummy input for the display. Then on blur, transfer the value to a hidden input and alter the text in the dummy. You might also want the reverse in place in case the user wants to alter the value: on focus, copy the value from the hidden input to the dummy. Here's a sample, no jQuery required, and if there are less than 5 characters in the input, it will make all *s instead.
var start = 0;
var end = 4;
var dummy_user = document.getElementById("user");
var actual_user = document.getElementById("hidden_user");
dummy_user.addEventListener("blur", function() {
actual_user.value = dummy_user.value;
if (dummy_user.value.length > 4) {
start = 2;
end = dummy_user.value.length - 2;
}
var val = "";
for (var i = 0; i < start; i++) {
val += dummy_user.value[i];
}
for (i = start; i < end; i++) {
val += "*";
}
for (i = end; i < dummy_user.value.length; i++) {
val += dummy_user.value[i];
}
dummy_user.value = val;
});
dummy_user.addEventListener("focus", function() {
this.value = actual_user.value;
});
<form action="">
<input type="text" name="user" id="user">
<input type="hidden" name="hidden_user" id="hidden_user" value="">
<input type="password" name="password">
<input type="submit" value="Sign in">
</form>