Related
I took this code from the internet and want to modify it so that regardless of which symbol I select, the x starts first (the computer in this case).
If I select to play with X, I will start first and the computer will play with O.
If I select to play with O, the computer will receive X and make the first move.
const selectBox = document.querySelector(".select-box"),
selectBtnX = selectBox.querySelector(".options .playerX"),
selectBtnO = selectBox.querySelector(".options .playerO"),
playBoard = document.querySelector(".play-board"),
players = document.querySelector(".players"),
allBox = document.querySelectorAll("section span"),
resultBox = document.querySelector(".result-box"),
wonText = resultBox.querySelector(".won-text"),
replayBtn = resultBox.querySelector("button");
let x = 'x';
let O = 'O';
window.onload = () => {
for (let i = 0; i < allBox.length; i++) {
allBox[i].setAttribute("onclick", "clickedBox(this)");
}
}
selectBtnX.onclick = () => {
selectBox.classList.add("hide");
playBoard.classList.add("show");
}
selectBtnO.onclick = () => {
selectBox.classList.add("hide");
playBoard.classList.add("show");
players.setAttribute("class", "players active player");
}
let playerXIcon = "fas fa-times",
playerOIcon = "far fa-circle",
playerSign = "X",
runBot = true;
function clickedBox(element) {
if (players.classList.contains("player")) {
playerSign = "O";
element.innerHTML = `<i class="${playerOIcon}"></i>`;
players.classList.remove("active");
element.setAttribute("id", playerSign);
} else {
element.innerHTML = `<i class="${playerXIcon}"></i>`;
element.setAttribute("id", playerSign);
players.classList.add("active");
}
selectWinner();
element.style.pointerEvents = "none";
playBoard.style.pointerEvents = "none";
let randomTimeDelay = ((Math.random() * 1000) + 200).toFixed();
setTimeout(() => {
bot(runBot);
}, randomTimeDelay);
}
function bot() {
let array = [];
if (runBot) {
playerSign = "O";
for (let i = 0; i < allBox.length; i++) {
if (allBox[i].childElementCount == 0) {
array.push(i);
}
}
let randomBox = array[Math.floor(Math.random() * array.length)];
if (array.length > 0) {
if (players.classList.contains("player")) {
playerSign = "X";
allBox[randomBox].innerHTML = `<i class="${playerXIcon}"></i>`;
allBox[randomBox].setAttribute("id", playerSign);
players.classList.add("active");
} else {
allBox[randomBox].innerHTML = `<i class="${playerOIcon}"></i>`;
players.classList.remove("active");
allBox[randomBox].setAttribute("id", playerSign);
}
selectWinner();
}
allBox[randomBox].style.pointerEvents = "none";
playBoard.style.pointerEvents = "auto";
playerSign = "X";
}
}
function getIdVal(classname) {
return document.querySelector(".box" + classname).id;
}
function checkIdSign(val1, val2, val3, sign) {
if (getIdVal(val1) == sign && getIdVal(val2) == sign && getIdVal(val3) == sign) {
return true;
}
}
function selectWinner() {
if (checkIdSign(1, 2, 3, playerSign) || checkIdSign(4, 5, 6, playerSign) || checkIdSign(7, 8, 9, playerSign) || checkIdSign(1, 4, 7, playerSign) || checkIdSign(2, 5, 8, playerSign) || checkIdSign(3, 6, 9, playerSign) || checkIdSign(1, 5, 9, playerSign) || checkIdSign(3, 5, 7, playerSign)) {
runBot = false;
bot(runBot);
setTimeout(() => {
resultBox.classList.add("show");
playBoard.classList.remove("show");
}, 700);
wonText.innerHTML = `<p>${playerSign}</p> wins!`;
} else {
if (getIdVal(1) != "" && getIdVal(2) != "" && getIdVal(3) != "" && getIdVal(4) != "" && getIdVal(5) != "" && getIdVal(6) != "" && getIdVal(7) != "" && getIdVal(8) != "" && getIdVal(9) != "") {
runBot = false;
bot(runBot);
setTimeout(() => {
resultBox.classList.add("show");
playBoard.classList.remove("show");
}, 700);
wonText.textContent = "It's a draw!";
}
}
}
replayBtn.onclick = () => {
window.location.reload();
}
I think when you select to play with 0, you should call bot to make a first move.
You can refer
selectBtnO.onclick = () => {
selectBox.classList.add("hide");
playBoard.classList.add("show");
players.setAttribute("class", "players active player");
bot(true); // call bot when you selet to play with O
}
I have 2 for loops, 1 outer for loop has 2000 items and the inner for loop has 800 items,my outer for loop is calling a function which calls another function and then I get the 800 items, basically i want to display 800 items in a table but there are columns where the data is inside the outerloop so that is why I need the nestedloop, when i run my browser get hangs, below is my code. Please help me find a way to achieve this.
function GetRowsAssetMaterialItems(
locationName,
expectDate,
urlAssetMaterial,
resultsAssetMaterialItems
) {
return $.ajax({
url: urlAssetMaterial,
method: "GET",
async: true,
headers: {
Accept: "application/json; odata=verbose",
},
success: (data) => {
debugger;
let arr = data.d.results;
let x = arr.filter((a) => {
var locationGatePass =
a.GatePassId.Title != null ? a.GatePassId.Title.toString() : "";
var expectedDateOfReturn = a.ExpectedDateOfReturn;
if (expectDate != "") {
var expectEndTIme = new Date(expectDate);
expectEndTIme.setUTCHours(23, 59, 59, 0);
var expectStartTIme = new Date(expectDate);
expectStartTIme.setUTCHours(0, 0, 0, 0);
if (
locationGatePass
.toLowerCase()
.includes(locationName.toLowerCase()) &&
expectedDateOfReturn <= expectEndTIme &&
expectedDateOfReturn >= expectStartTIme
) {
return a;
}
} else {
if (
locationGatePass.toLowerCase().includes(locationName.toLowerCase())
) {
return a;
}
}
});
resultsAssetMaterialItems = resultsAssetMaterialItems.concat(x);
if (data.d.__next) {
urlAssetMaterial = data.d.__next;
GetRowsAssetMaterialItems(
locationName,
expectDate,
urlAssetMaterial,
resultsAssetMaterialItems
);
} else {
var result = [];
$.each(resultsAssetMaterialItems, function (i, e) {
var matchingItems = $.grep(result, function (item) {
return item.GatePassId.Title === e.GatePassId.Title;
});
if (matchingItems.length === 0) {
result.push(e);
}
});
for (var i = 0; i < result.length; i++) { 1st for loop where items are 2000
var item = result[i];
var sNo = i + 1;
var Atitle = item.Title;
var AMaterialCode = item.MaterialCode;
var AMaterialDescription = item.MaterialDescription;
gatePassMaster(Atitle,AMaterialCode,AMaterialDescription);
}
setTimeout('$("#retriveData").removeAttr("disabled")', 1000);
loadTable();
}
},
});
}
function gatePassMaster(
Atitle,
AMaterialCode,
AMaterialDescription,
AQuantity,
AUnit,
ABatchNo,
AExpectedDateOfReturn,
AReturnedDate,
AGatePassMasterID,
ARemarks,
sNo
) {
debugger;
//$("#pending_rgp tr").remove();
var startDD = $("#startDate").val();
var endDate = $("#endDate").val();
var dateStartend = new Date(startDD);
dateStartend.setUTCHours(23, 59, 59, 0);
var dateStartfirst = new Date(startDD);
dateStartfirst.setUTCHours(00, 00, 00, 0);
var dateEnd = new Date(endDate);
dateEnd.setUTCHours(23, 59, 59, 0);
var dateEndstart = new Date(endDate);
dateEndstart.setUTCHours(00, 00, 00, 0);
var currentTime = new Date();
var getmonth = currentTime.getMonth();
var getyear = currentTime.getFullYear();
// returns the month (from 0 to 11)
var aprilmonth = 04;
var marchmonth = 03;
// returns the day of the month (from 1 to 31)
var aprilday = 01;
var marchday = 31;
var aprilyear = "";
// returns the year (four digits)
if (getmonth >= 3) {
aprilyear = currentTime.getFullYear();
} else {
aprilyear = currentTime.getFullYear() - 1;
}
var startapril = aprilmonth + "-" + aprilday + "-" + aprilyear;
var aprilstart = new Date(startapril);
aprilstart.setUTCHours(24, 0, 0, 0);
var marchyear = "";
if (getmonth > 2) {
marchyear = currentTime.getFullYear() + 1;
} else {
marchyear = currentTime.getFullYear();
}
var endMarch = marchmonth + "-" + marchday + "-" + marchyear;
var marchend = new Date(endMarch);
marchend.setUTCHours(47, 59, 59, 0);
console.log(marchend, aprilstart);
GetRowsGatePassMasterItems(
Atitle,
AMaterialCode,
AMaterialDescription,
AQuantity,
AUnit,
ABatchNo,
AExpectedDateOfReturn,
AReturnedDate,
AGatePassMasterID,
ARemarks,
sNo,
startDD,
endDate,
dateStartfirst,
dateStartend,
dateEnd,
dateEndstart,
aprilstart,
marchend,
locationName
);
}
function GetRowsGatePassMasterItems(
Atitle,
AMaterialCode,
AMaterialDescription,
AQuantity,
AUnit,
ABatchNo,
AExpectedDateOfReturn,
AReturnedDate,
AGatePassMasterID,
ARemarks,
sNo,
startDD,
endDate,
dateStartfirst,
dateStartend,
dateEnd,
dateEndstart,
aprilstart,
marchend,
locationName
) {
debugger;
if (resultsGatePassMasterAllItems != undefined) {
let arr = resultsGatePassMasterAllItems;
let x = arr.filter((a) => {
var gatePassId = a.ID != null ? a.ID.toString() : "";
var locationGatePass = a.Title != null ? a.Title.toString() : "";
var createdDate = a.Created;
if (startDD != "" && endDate != "") {
if (
gatePassId == AGatePassMasterID &&
locationGatePass.toLowerCase().includes(locationName.toLowerCase()) &&
createdDate >= dateStartfirst.toISOString() &&
createdDate <= dateEnd.toISOString()
) {
return a;
}
} else if (startDD != "" && endDate == "") {
if (
gatePassId == AGatePassMasterID &&
locationGatePass.toLowerCase().includes(locationName.toLowerCase()) &&
createdDate >= dateStartfirst.toISOString() &&
createdDate <= dateStartend.toISOString()
) {
return a;
}
} else if (startDD == "" && endDate != "") {
if (
gatePassId == AGatePassMasterID &&
locationGatePass.toLowerCase().includes(locationName.toLowerCase()) &&
createdDate >= dateEndstart.toISOString() &&
createdDate <= dateEnd.toISOString()
) {
return a;
}
} else {
if (
gatePassId == AGatePassMasterID &&
locationGatePass.toLowerCase().includes(locationName.toLowerCase()) &&
createdDate >= aprilstart.toISOString() &&
createdDate <= marchend.toISOString()
) {
return a;
}
}
});
resultsGatePassMasterItems1 = resultsGatePassMasterItems1.concat(x);
debugger;
var result = [];
$.each(resultsGatePassMasterItems1, function (i, e) {
var matchingItems = $.grep(result, function (item) {
return item.Title === e.Title;
});
if (matchingItems.length === 0) {
result.push(e);
}
console.log(matchingItems.length);
});
for (var i = 0; i < result.length; i++) { // inner loop where items are 800
var item = result[i];
if (item.ID == AGatePassMasterID && item.GatePassType == "Returnable") {
number = number + 1;
var GatePassNumber = item.Title;
var CreatedDate = item.Created;
var CreatedBy = item.Author.Title;
var ApprovedBy = item.ApprovedByName;
var Status = item.Status;
if (Status.toLowerCase() == "pending") {
Status = "Open";
} else if (Status.toLowerCase() == "approved") {
Status = "Close";
} else if (Status.toLowerCase() == "rejected") {
Status = "Rejected";
}
results.push({
AtitleName: Atitle,
AMaterialCode: AMaterialCode,
AMaterialDescription: AMaterialDescription,
GatePassNumber: GatePassNumber,
});
excelData.push({
"Sr.No": number,
"Gate Pass Date": creat,
"Gate Pass Number": GatePassNumber,
Vendor: VendorName,
"Material Code": AMaterialCode,
"Material Description": AMaterialDescription,
});
}
}
loadTable();
console.log("finalresult", results);
}
}
I have a string and need to check with and get whether the following strings overlap with the start and end of my target string:
target string: "click on the Run"
search strings: "the Run button to", "code and click on"
Apparently:
"the Run button to" is overlapped at the end of target "click on the Run"
"code and click on" is overlapped at the start of target "click on the Run"
Both, "the Run" and "click on" will be the desired results.
I have come up with a function to check and get the overlapped results for the cases at the start and at the end separately.
Question:
But my code could not be able to get the expected results only if I know how the search string overlapped with the target string in the very first place. And how can I combine the searched results in one go as well?
function findOverlapAtEnd(a, b) {
if (b.length === 2) {
return "";
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.endsWith(b)) {
return b;
}
return findOverlapAtEnd(a, b.substring(0, b.length - 1));
}
function findOverlapAtStart(a, b) {
if (b.length === 2) {
return "";
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.startsWith(b)) {
return b;
}
return findOverlapAtStart(a, b.substring(1));
}
console.log(findOverlapAtEnd("click on the Run", "the Run button to"))
console.log(findOverlapAtStart("click on the Run", "code and click on"))
edited:
case in the middle is also considered, e.g.:
target string: "click on the Run"
search strings: "on the"
Return value: "on the"
You may try this
function findOverlapAtEnd(a, b, min) {
if (b.length <= min) {
return '';
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.endsWith(b)) {
return b;
}
return findOverlapAtEnd(a, b.substring(0, b.length - 1), min);
}
function findOverlapAtStart(a, b, min) {
if (b.length <= min) {
return '';
}
if (a.indexOf(b) >= 0) {
return b;
}
if (a.startsWith(b)) {
return b;
}
return findOverlapAtStart(a, b.substring(1), min);
}
const GetOverlappingSection = (target, search, min) => {
if (target.length < search.length) {
const tmp = target;
target = search;
search = tmp;
}
let overlap1 = findOverlapAtStart(target, search, min);
if (overlap1.length === 0) {
overlap1 = findOverlapAtEnd(target, search, min);
}
return overlap1;
};
const removeEmptyKeyword = overlap => {
let tmpFinaloverlap = [];
overlap.forEach((key, idx) => {
if (!(key.trim().length === 0)) {
tmpFinaloverlap = [...tmpFinaloverlap, key];
}
});
return tmpFinaloverlap;
};
// let overlap = ['click on','the Run']
const GetOverlappingOfKeyowrd1And2 = (keywordSet1, keywordSet2,min) => {
let resultSetoverlap = [];
let tmpresultSetoverlap = [];
keywordSet1.forEach(key =>
keywordSet2.forEach(k2 => {
tmpresultSetoverlap = [
...tmpresultSetoverlap,
GetOverlappingSection(key, k2, min),
];
})
);
// get the resultSetoverlap
tmpresultSetoverlap.forEach(element => {
if (element.length > 0) {
resultSetoverlap = [...resultSetoverlap, element];
}
});
return resultSetoverlap;
};
const min = 2;
//To handle overlapping issue in overlapping set, that casuing
overlap.forEach((key, idx) => {
if (idx < overlap.length - 1) {
for (let i = idx + 1; i < overlap.length; i++) {
console.log(`key: ${key}`);
console.log(`search: ${overlap[i]}`);
let overlapSection = GetOverlappingSection(key, overlap[i], min);
if (overlapSection.length > 0) {
console.log(`overlapSection: ${overlapSection}`);
overlap[idx] = overlap[idx].replace(overlapSection, '');
}
}
}
});
overlap = removeEmptyKeyword(overlap);
console.log(overlap);
overlap.forEach(key => {
keywordSet2 = keywordSet2.map((k1, idx) => {
console.log(`checking overlap keyword:'${key}' in '${k1}'`);
return k1.replace(key, '');
});
});
overlap.forEach(key => {
keywordSet1 = keywordSet1.map((k1, idx) => {
console.log(`checking overlap keyword:'${key}' in '${k1}'`);
return k1.replace(key, '');
});
});
keywordSet2 = removeEmptyKeyword(keywordSet2);
keywordSet1 = removeEmptyKeyword(keywordSet1);
overlap.forEach(key => {
text = text.replace(key, `$#k1k2$&$`);
});
keywordSet1.forEach(key => {
text = text.replace(key, `$#k1$&$`);
});
keywordSet2.forEach(key => {
text = text.replace(key, `$#k2$&$`);
});
console.log(`ResultSetoverlap after processing:${text}`);
Because I need to decompress and I find these logic puzzles fun, here's my solution to the problem...
https://highdex.net/begin_end_overlap.htm
You can view source of the page to see JavaScript code I used. But just in case I ever take that page down, here's the important function...
function GetOverlappingSection(str1, str2, minOverlapLen = 4) {
var work1 = str1;
var work2 = str2;
var w1Len = work1.length;
var w2Len = work2.length;
var resultStr = "";
var foundResult = false;
var workIndex;
if (minOverlapLen < 1) { minOverlapLen = 1; }
else if (minOverlapLen > (w1Len > w2Len ? w2Len : w1Len)) { minOverlapLen = (w1Len > w2Len ? w2Len : w1Len); }
//debugger;
//we have four loops to go through. We trim each string down from each end and see if it matches either end of the other string.
for (var i1f = 0; i1f < w1Len; i1f++) {
workIndex = work2.indexOf(work1);
if (workIndex == 0 || (workIndex != -1 && workIndex == w2Len - work1.length)) {
//we found a match!
foundResult = true;
resultStr = work1;
break;
}
work1 = work1.substr(1);
if (work1.length < minOverlapLen) { break; }
}
if (!foundResult) {
//debugger;
//reset the work vars...
work1 = str1;
for (var i1b = 0; i1b < w1Len; i1b++) {
workIndex = work2.indexOf(work1);
if (workIndex == 0 || (workIndex != -1 && workIndex == w2Len - work1.length)) {
//we found a match!
foundResult = true;
resultStr = work1;
break;
}
work1 = work1.substr(0, work1.length - 1);
if (work1.length < minOverlapLen) { break; }
}
}
if (!foundResult) {
//debugger;
//reset the work vars...
work1 = str1;
for (var i2f = 0; i2f < w2Len; i2f++) {
workIndex = work1.indexOf(work2);
if (workIndex == 0 || (workIndex != -1 && workIndex == w1Len - work2.length)) {
//we found a match!
foundResult = true;
resultStr = work2;
break;
}
work2 = work2.substr(1);
if (work2.length < minOverlapLen) { break; }
}
}
if (!foundResult) {
//debugger;
//reset the work vars...
work2 = str2;
for (var i2b = 0; i2b < w2Len; i2b++) {
workIndex = work1.indexOf(work2);
if (workIndex == 0 || (workIndex != -1 && workIndex == w1Len - work2.length)) {
//we found a match!
foundResult = true;
resultStr = work2;
break;
}
work2 = work2.substr(0, work2.length - 1);
if (work2.length < minOverlapLen) { break; }
}
}
return resultStr;
}
Hopefully that's helpful.
The following jquery I am using in my jsp page for adding an autocomplete option to a text field which is having an id mytextfield.
jQuery(function(){
$("#mytextfield").autocomplete("popuppages/listall.jsp");
});
Within the same page, there are some cases in which I will have to remove this autocomplete feature from this text field. ( That is the same field will have to act as a textfield without autocomplete based on the user's inputs to previous fields and options)
Is there any way so that I could remove this newly added 'autocomplete' property from the particular item, that is from $("#mytextfield").
What actually I want to know is is there any option for removing added property
Incase anyone want to refer that autocomplete code, I have attached it below..
;(function($) {
$.fn.extend({
autocomplete: function(urlOrData, options) {
var isUrl = typeof urlOrData == "string";
options = $.extend({}, $.Autocompleter.defaults, {
url: isUrl ? urlOrData : null,
data: isUrl ? null : urlOrData,
delay: isUrl ? $.Autocompleter.defaults.delay : 10,
max: options && !options.scroll ? 10 : 150
}, options);
// if highlight is set to false, replace it with a do-nothing function
options.highlight = options.highlight || function(value) { return value; };
// if the formatMatch option is not specified, then use formatItem for backwards compatibility
options.formatMatch = options.formatMatch || options.formatItem;
return this.each(function() {
new $.Autocompleter(this, options);
});
},
result: function(handler) {
return this.bind("result", handler);
},
search: function(handler) {
return this.trigger("search", [handler]);
},
flushCache: function() {
return this.trigger("flushCache");
},
setOptions: function(options){
return this.trigger("setOptions", [options]);
},
unautocomplete: function() {
return this.trigger("unautocomplete");
}
});
$.Autocompleter = function(input, options) {
var KEY = {
UP: 38,
DOWN: 40,
DEL: 46,
TAB: 9,
RETURN: 13,
ESC: 27,
COMMA: 188,
PAGEUP: 33,
PAGEDOWN: 34,
BACKSPACE: 8
};
// Create $ object for input element
var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
var timeout;
var previousValue = "";
var cache = $.Autocompleter.Cache(options);
var hasFocus = 0;
var lastKeyPressCode;
var config = {
mouseDownOnSelect: false
};
var select = $.Autocompleter.Select(options, input, selectCurrent, config);
var blockSubmit;
// prevent form submit in opera when selecting with return key
$.browser.opera && $(input.form).bind("submit.autocomplete", function() {
if (blockSubmit) {
blockSubmit = false;
return false;
}
});
// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
// a keypress means the input has focus
// avoids issue where input had focus before the autocomplete was applied
hasFocus = 1;
// track last key pressed
lastKeyPressCode = event.keyCode;
switch(event.keyCode) {
case KEY.UP:
event.preventDefault();
if ( select.visible() ) {
select.prev();
} else {
onChange(0, true);
}
break;
case KEY.DOWN:
event.preventDefault();
if ( select.visible() ) {
select.next();
} else {
onChange(0, true);
}
break;
case KEY.PAGEUP:
event.preventDefault();
if ( select.visible() ) {
select.pageUp();
} else {
onChange(0, true);
}
break;
case KEY.PAGEDOWN:
event.preventDefault();
if ( select.visible() ) {
select.pageDown();
} else {
onChange(0, true);
}
break;
// matches also semicolon
case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
case KEY.TAB:
case KEY.RETURN:
if( selectCurrent() ) {
// stop default to prevent a form submit, Opera needs special handling
event.preventDefault();
blockSubmit = true;
return false;
}
break;
case KEY.ESC:
select.hide();
break;
default:
clearTimeout(timeout);
timeout = setTimeout(onChange, options.delay);
break;
}
}).focus(function(){
// track whether the field has focus, we shouldn't process any
// results if the field no longer has focus
hasFocus++;
}).blur(function() {
hasFocus = 0;
if (!config.mouseDownOnSelect) {
hideResults();
}
}).click(function() {
// show select when clicking in a focused field
if ( hasFocus++ > 1 && !select.visible() ) {
onChange(0, true);
}
}).bind("search", function() {
// TODO why not just specifying both arguments?
var fn = (arguments.length > 1) ? arguments[1] : null;
function findValueCallback(q, data) {
var result;
if( data && data.length ) {
for (var i=0; i < data.length; i++) {
if( data[i].result.toLowerCase() == q.toLowerCase() ) {
result = data[i];
break;
}
}
}
if( typeof fn == "function" ) fn(result);
else $input.trigger("result", result && [result.data, result.value]);
}
$.each(trimWords($input.val()), function(i, value) {
request(value, findValueCallback, findValueCallback);
});
}).bind("flushCache", function() {
cache.flush();
}).bind("setOptions", function() {
$.extend(options, arguments[1]);
// if we've updated the data, repopulate
if ( "data" in arguments[1] )
cache.populate();
}).bind("unautocomplete", function() {
select.unbind();
$input.unbind();
$(input.form).unbind(".autocomplete");
});
function selectCurrent() {
var selected = select.selected();
if( !selected )
return false;
var v = selected.result;
previousValue = v;
if ( options.multiple ) {
var words = trimWords($input.val());
if ( words.length > 1 ) {
var seperator = options.multipleSeparator.length;
var cursorAt = $(input).selection().start;
var wordAt, progress = 0;
$.each(words, function(i, word) {
progress += word.length;
if (cursorAt <= progress) {
wordAt = i;
return false;
}
progress += seperator;
});
words[wordAt] = v;
// TODO this should set the cursor to the right position, but it gets overriden somewhere
//$.Autocompleter.Selection(input, progress + seperator, progress + seperator);
v = words.join( options.multipleSeparator );
}
v += options.multipleSeparator;
}
$input.val(v);
hideResultsNow();
$input.trigger("result", [selected.data, selected.value]);
return true;
}
function onChange(crap, skipPrevCheck) {
if( lastKeyPressCode == KEY.DEL ) {
select.hide();
return;
}
var currentValue = $input.val();
if ( !skipPrevCheck && currentValue == previousValue )
return;
previousValue = currentValue;
currentValue = lastWord(currentValue);
if ( currentValue.length >= options.minChars) {
$input.addClass(options.loadingClass);
if (!options.matchCase)
currentValue = currentValue.toLowerCase();
request(currentValue, receiveData, hideResultsNow);
} else {
stopLoading();
select.hide();
}
};
function trimWords(value) {
if (!value)
return [""];
if (!options.multiple)
return [$.trim(value)];
return $.map(value.split(options.multipleSeparator), function(word) {
return $.trim(value).length ? $.trim(word) : null;
});
}
function lastWord(value) {
if ( !options.multiple )
return value;
var words = trimWords(value);
if (words.length == 1)
return words[0];
var cursorAt = $(input).selection().start;
if (cursorAt == value.length) {
words = trimWords(value)
} else {
words = trimWords(value.replace(value.substring(cursorAt), ""));
}
return words[words.length - 1];
}
// fills in the input box w/the first match (assumed to be the best match)
// q: the term entered
// sValue: the first matching result
function autoFill(q, sValue){
// autofill in the complete box w/the first match as long as the user hasn't entered in more data
// if the last user key pressed was backspace, don't autofill
if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
// fill in the value (keep the case the user has typed)
$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
// select the portion of the value not typed by the user (so the next character will erase)
$(input).selection(previousValue.length, previousValue.length + sValue.length);
}
};
function hideResults() {
clearTimeout(timeout);
timeout = setTimeout(hideResultsNow, 200);
};
function hideResultsNow() {
var wasVisible = select.visible();
select.hide();
clearTimeout(timeout);
stopLoading();
if (options.mustMatch) {
// call search and run callback
$input.search(
function (result){
// if no value found, clear the input box
if( !result ) {
if (options.multiple) {
var words = trimWords($input.val()).slice(0, -1);
$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
}
else {
$input.val( "" );
$input.trigger("result", null);
}
}
}
);
}
};
function receiveData(q, data) {
if ( data && data.length && hasFocus ) {
stopLoading();
select.display(data, q);
autoFill(q, data[0].value);
select.show();
} else {
hideResultsNow();
}
};
function request(term, success, failure) {
if (!options.matchCase)
term = term.toLowerCase();
var data = cache.load(term);
// recieve the cached data
if (data && data.length) {
success(term, data);
// if an AJAX url has been supplied, try loading the data now
} else if( (typeof options.url == "string") && (options.url.length > 0) ){
var extraParams = {
timestamp: +new Date()
};
$.each(options.extraParams, function(key, param) {
extraParams[key] = typeof param == "function" ? param() : param;
});
$.ajax({
// try to leverage ajaxQueue plugin to abort previous requests
mode: "abort",
// limit abortion to this input
port: "autocomplete" + input.name,
dataType: options.dataType,
url: options.url,
data: $.extend({
q: lastWord(term),
limit: options.max
}, extraParams),
success: function(data) {
var parsed = options.parse && options.parse(data) || parse(data);
cache.add(term, parsed);
success(term, parsed);
}
});
} else {
// if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
select.emptyList();
failure(term);
}
};
function parse(data) {
var parsed = [];
var rows = data.split("\n");
for (var i=0; i < rows.length; i++) {
var row = $.trim(rows[i]);
if (row) {
row = row.split("|");
parsed[parsed.length] = {
data: row,
value: row[0],
result: options.formatResult && options.formatResult(row, row[0]) || row[0]
};
}
}
return parsed;
};
function stopLoading() {
$input.removeClass(options.loadingClass);
};
};
$.Autocompleter.defaults = {
inputClass: "ac_input",
resultsClass: "ac_results",
loadingClass: "ac_loading",
minChars: 1,
delay: 400,
matchCase: false,
matchSubset: true,
matchContains: false,
cacheLength: 10,
max: 100,
mustMatch: false,
extraParams: {},
selectFirst: true,
formatItem: function(row) { return row[0]; },
formatMatch: null,
autoFill: false,
width: 0,
multiple: false,
multipleSeparator: ", ",
highlight: function(value, term) {
return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
},
scroll: true,
scrollHeight: 180
};
$.Autocompleter.Cache = function(options) {
var data = {};
var length = 0;
function matchSubset(s, sub) {
if (!options.matchCase)
s = s.toLowerCase();
var i = s.indexOf(sub);
if (options.matchContains == "word"){
i = s.toLowerCase().search("\\b" + sub.toLowerCase());
}
if (i == -1) return false;
return i == 0 || options.matchContains;
};
function add(q, value) {
if (length > options.cacheLength){
flush();
}
if (!data[q]){
length++;
}
data[q] = value;
}
function populate(){
if( !options.data ) return false;
// track the matches
var stMatchSets = {},
nullData = 0;
// no url was specified, we need to adjust the cache length to make sure it fits the local data store
if( !options.url ) options.cacheLength = 1;
// track all options for minChars = 0
stMatchSets[""] = [];
// loop through the array and create a lookup structure
for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
var rawValue = options.data[i];
// if rawValue is a string, make an array otherwise just reference the array
rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
var value = options.formatMatch(rawValue, i+1, options.data.length);
if ( value === false )
continue;
var firstChar = value.charAt(0).toLowerCase();
// if no lookup array for this character exists, look it up now
if( !stMatchSets[firstChar] )
stMatchSets[firstChar] = [];
// if the match is a string
var row = {
value: value,
data: rawValue,
result: options.formatResult && options.formatResult(rawValue) || value
};
// push the current match into the set list
stMatchSets[firstChar].push(row);
// keep track of minChars zero items
if ( nullData++ < options.max ) {
stMatchSets[""].push(row);
}
};
// add the data items to the cache
$.each(stMatchSets, function(i, value) {
// increase the cache size
options.cacheLength++;
// add to the cache
add(i, value);
});
}
// populate any existing data
setTimeout(populate, 25);
function flush(){
data = {};
length = 0;
}
return {
flush: flush,
add: add,
populate: populate,
load: function(q) {
if (!options.cacheLength || !length)
return null;
/*
* if dealing w/local data and matchContains than we must make sure
* to loop through all the data collections looking for matches
*/
if( !options.url && options.matchContains ){
// track all matches
var csub = [];
// loop through all the data grids for matches
for( var k in data ){
// don't search through the stMatchSets[""] (minChars: 0) cache
// this prevents duplicates
if( k.length > 0 ){
var c = data[k];
$.each(c, function(i, x) {
// if we've got a match, add it to the array
if (matchSubset(x.value, q)) {
csub.push(x);
}
});
}
}
return csub;
} else
// if the exact item exists, use it
if (data[q]){
return data[q];
} else
if (options.matchSubset) {
for (var i = q.length - 1; i >= options.minChars; i--) {
var c = data[q.substr(0, i)];
if (c) {
var csub = [];
$.each(c, function(i, x) {
if (matchSubset(x.value, q)) {
csub[csub.length] = x;
}
});
return csub;
}
}
}
return null;
}
};
};
$.Autocompleter.Select = function (options, input, select, config) {
var CLASSES = {
ACTIVE: "ac_over"
};
var listItems,
active = -1,
data,
term = "",
needsInit = true,
element,
list;
// Create results
function init() {
if (!needsInit)
return;
element = $("<div/>")
.hide()
.addClass(options.resultsClass)
.css("position", "absolute")
.appendTo(document.body);
list = $("<ul/>").appendTo(element).mouseover( function(event) {
if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
$(target(event)).addClass(CLASSES.ACTIVE);
}
}).click(function(event) {
$(target(event)).addClass(CLASSES.ACTIVE);
select();
// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
input.focus();
return false;
}).mousedown(function() {
config.mouseDownOnSelect = true;
}).mouseup(function() {
config.mouseDownOnSelect = false;
});
if( options.width > 0 )
element.css("width", options.width);
needsInit = false;
}
function target(event) {
var element = event.target;
while(element && element.tagName != "LI")
element = element.parentNode;
// more fun with IE, sometimes event.target is empty, just ignore it then
if(!element)
return [];
return element;
}
function moveSelect(step) {
listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
movePosition(step);
var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
if(options.scroll) {
var offset = 0;
listItems.slice(0, active).each(function() {
offset += this.offsetHeight;
});
if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
} else if(offset < list.scrollTop()) {
list.scrollTop(offset);
}
}
};
function movePosition(step) {
active += step;
if (active < 0) {
active = listItems.size() - 1;
} else if (active >= listItems.size()) {
active = 0;
}
}
function limitNumberOfItems(available) {
return options.max && options.max < available
? options.max
: available;
}
function fillList() {
list.empty();
var max = limitNumberOfItems(data.length);
for (var i=0; i < max; i++) {
if (!data[i])
continue;
var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
if ( formatted === false )
continue;
var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
$.data(li, "ac_data", data[i]);
}
listItems = list.find("li");
if ( options.selectFirst ) {
listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
active = 0;
}
// apply bgiframe if available
if ( $.fn.bgiframe )
list.bgiframe();
}
return {
display: function(d, q) {
init();
data = d;
term = q;
fillList();
},
next: function() {
moveSelect(1);
},
prev: function() {
moveSelect(-1);
},
pageUp: function() {
if (active != 0 && active - 8 < 0) {
moveSelect( -active );
} else {
moveSelect(-8);
}
},
pageDown: function() {
if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
moveSelect( listItems.size() - 1 - active );
} else {
moveSelect(8);
}
},
hide: function() {
element && element.hide();
listItems && listItems.removeClass(CLASSES.ACTIVE);
active = -1;
},
visible : function() {
return element && element.is(":visible");
},
current: function() {
return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
},
show: function() {
var offset = $(input).offset();
element.css({
width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
top: offset.top + input.offsetHeight,
left: offset.left
}).show();
if(options.scroll) {
list.scrollTop(0);
list.css({
maxHeight: options.scrollHeight,
overflow: 'auto'
});
if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
var listHeight = 0;
listItems.each(function() {
listHeight += this.offsetHeight;
});
var scrollbarsVisible = listHeight > options.scrollHeight;
list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
if (!scrollbarsVisible) {
// IE doesn't recalculate width when scrollbar disappears
listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
}
}
}
},
selected: function() {
var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
return selected && selected.length && $.data(selected[0], "ac_data");
},
emptyList: function (){
list && list.empty();
},
unbind: function() {
element && element.remove();
}
};
};
$.fn.selection = function(start, end) {
if (start !== undefined) {
return this.each(function() {
if( this.createTextRange ){
var selRange = this.createTextRange();
if (end === undefined || start == end) {
selRange.move("character", start);
selRange.select();
} else {
selRange.collapse(true);
selRange.moveStart("character", start);
selRange.moveEnd("character", end);
selRange.select();
}
} else if( this.setSelectionRange ){
this.setSelectionRange(start, end);
} else if( this.selectionStart ){
this.selectionStart = start;
this.selectionEnd = end;
}
});
}
var field = this[0];
if ( field.createTextRange ) {
var range = document.selection.createRange(),
orig = field.value,
teststring = "<->",
textLength = range.text.length;
range.text = teststring;
var caretAt = field.value.indexOf(teststring);
field.value = orig;
this.selection(caretAt, caretAt + textLength);
return {
start: caretAt,
end: caretAt + textLength
}
} else if( field.selectionStart !== undefined ){
return {
start: field.selectionStart,
end: field.selectionEnd
}
}
};
})(jQuery);
Looks like you are looking for destroy or disable method of autocomplete..
Check Documentation...
destroy
disable
$("#mytextfield").autocomplete( "destroy" )
$("#mytextfield").autocomplete( "disable" )
The difference is after destroy you cannot enable it back...but after disable by using enable you can enable it back..
You can use .removeAttr()
$(target).removeAttr('propertyName');
This will totally remove that property.
But if you want to change any property then use .prop() or .attr()
Are there any good number picker for jquery (or standalone js)?
I would like a number picker where there is a max and min number that the user can choose from. Also, it have other options such as displaying odd number or even number or prime number or a range of number whereby some numbers in between are skipped.
Using a select to do this you can create an array with the numbers to skip and do a for loop to write the options:
int minNumber = 0;
int maxNumber = 10;
int[] skipThese = { 5, 7 };
for (int i = minNumber; i <= maxNumber; i++)
{
if(!skipThese.Contains(i)) Response.Write(String.Concat("<option value=\"", i, "\">", i, "</option>"));
}
You can do this with razor or any other way to output the HTML.
You can also do this with jQuery, dynamicaly, following the same idea:
$(document).ready(function() {
var minNumber = 0;
var maxNumber = 10;
var skipThese = [5, 7];
for (var i = minNumber; i <= maxNumber; i++) {
if ($.inArray(i, skipThese) == -1) $('#selectListID').append("<option value=\"" + i + "\">" + i + "</option>");
}
});
Edit:
Or you can use the C# code above in an aspx page and load it with AJAX from the page:
Create a select box in the page:
<select name="numPicker" id="numPicker">
<option>Loading...</option>
</select>
In a script in this page you could use jQuery's ajax() to fetch the data and populate the <select>:
$(document).ready(function() {
var numPickerSelect = $("#numPicker");
$.ajax({
url: 'url/to/page.aspx',
type: 'post'
success: function(data) {
numPickerSelect.find('option').remove(); // Remove the options in the select field
numPickerSelect.append(data); // Load the content generated by the server into the select field
},
error: function() {
alert('An error has ocurred!');
}
});
//Or use this (not sure if will work)
numPickerSelect.load("url/to/page.aspx");
});
I have used this. You should be able to modify to add extra options such as min and max fairly easily.
// Make a control only accept numeric input
// eg, $("#myedit").numeric()
// $("#myedit").numeric({alow: ' ,.'})
// $("#myedit").numeric({decimals: 2})
(function($) {
$.fn.alphanumeric = function(p) {
if (p == 'destroy') {
$(this).unbind('keypress');
$(this).unbind('blur');
return;
}
p = $.extend({
ichars: "!##$%^&*()+=[]\\\';,/{}|\":<>?~`.- ",
nchars: "",
allow: "",
decimals: null
}, p);
return this.each
(
function() {
if (p.nocaps) p.nchars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (p.allcaps) p.nchars += "abcdefghijklmnopqrstuvwxyz";
s = p.allow.split('');
for (i = 0; i < s.length; i++) if (p.ichars.indexOf(s[i]) != -1) s[i] = "\\" + s[i];
p.allow = s.join('|');
var reg = new RegExp(p.allow, 'gi');
var ch = p.ichars + p.nchars;
ch = ch.replace(reg, '');
var dp = p.decimals;
var isInteger = function(val) {
var objRegExp = /(^-?\d\d*$)/;
return objRegExp.test(val);
};
var isNumeric = function(val) {
// If the last digit is a . then add a 0 before testing so if they type 25. it will be accepted
var lastChar = val.substring(val.length - 1);
if (lastChar == ".") val = val + "0";
var objRegExp = new RegExp("^\\s*-?(\\d+(\\.\\d{1," + dp + "})?|\\.\\d{1," + dp + "})\\s*$", "g");
if (dp == -1)
objRegExp = new RegExp("^\\s*-?(\\d+(\\.\\d{1,25})?|\\.\\d{1,25})\\s*$", "g");
var result = objRegExp.test(val);
return result;
};
$(this).blur(function(e) {
var text = $(this).val();
if (dp != null) {
if (dp == 0) {
if (!isInteger(text)) {
$(this).val('');
e.preventDefault();
}
}
else {
if (!isNumeric(text)) {
$(this).val('');
e.preventDefault();
}
}
} else {
var c = text.split('')
for (i = 0; i < text.length; i++) {
if (ch.indexOf(c[i]) != -1) {
$(this).val('');
e.preventDefault();
};
}
}
});
$(this).keypress
(
function(e) {
switch (e.which) {
//Firefox fix, for ignoring specific presses
case 8: // backspace key
return true;
case 46: // delete key
return true;
};
if (dp != null) {
if (e.which == 32) { e.preventDefault(); return false; }
var range = getRange(this);
var typed = String.fromCharCode(e.which);
var text = $(this).val().substr(0, range.start) + typed + $(this).val().substr(range.start);
if (dp == 0) {
if (!isInteger(text)) e.preventDefault();
}
else {
if (!isNumeric(text)) e.preventDefault();
}
return;
}
if (!e.charCode) k = String.fromCharCode(e.which);
else k = String.fromCharCode(e.charCode);
if (ch.indexOf(k) != -1) e.preventDefault();
if (e.ctrlKey && k == 'v') e.preventDefault();
}
);
$(this).bind('contextmenu', function() { return false });
}
);
};
$.fn.numeric = function(p) {
if (p == 'destroy') {
$(this).unbind('keypress');
$(this).unbind('blur');
return;
}
var az = "abcdefghijklmnopqrstuvwxyz";
az += az.toUpperCase();
var opts = {};
if (!isNaN(p)) {
opts = $.extend({
nchars: az
}, { decimals: p });
} else {
opts = $.extend({
nchars: az
}, p);
}
return this.each(function() {
$(this).alphanumeric(opts);
}
);
};
$.fn.integer = function(p) {
if (p == 'destroy') {
$(this).unbind('keypress');
$(this).unbind('blur');
return;
}
var az = "abcdefghijklmnopqrstuvwxyz";
az += az.toUpperCase();
p = {
nchars: az,
allow: '-',
decimals: 0
};
return this.each(function() {
$(this).alphanumeric(p);
}
);
};
$.fn.alpha = function(p) {
if (p == 'destroy') {
$(this).unbind('keypress');
$(this).unbind('blur');
return;
}
var nm = "1234567890";
p = $.extend({
nchars: nm
}, p);
return this.each(function() {
$(this).alphanumeric(p);
}
);
};
})(jQuery);