I am currently testing touchstart functionality on my device (Samsung galaxy S2) for my game. I am programming using javascript and jquery wrapped under phonegap in android and currently having issues as follows:
my touch start event (e.g triggering an attack button "touchstart" event to run some javascript to perform the attack action) causes my screen to become temporarily fuzzy, then back to normal in less than a second, so more like a screen flicker where images become jittery). I am not using css transforms or transitions just plain css and images.
Can someone please let me know if they have encountered moreorless similar issues to mine. A bit at a loss whether it is a hardware or touchstart issue where i can solve that problem.
Sample Javascript below for my navigation controls (left, up, down, right touchstart tap):
if ('ontouchstart' in document.documentElement) {
var left = document.getElementById('left');
left.addEventListener("touchstart", function(e){
if(controlsPlayerChar == '')
{
return false;
}
var l_oldCell = $('#' + controlsPlayerChar).parent().attr('id');
var l_xy = l_oldCell.split('_');
var l_x = l_xy[0];
var l_y = l_xy[1];
if(l_y == 1)
{
direction = "left";
setCharDynamics(controlsPlayerChar);
return false;
}
var l_newCell = l_x + '_' + (parseInt(l_y) - 1);
// validate if next cell is empty
if($('#' + l_newCell + ':has(".shadow")').val() != undefined
|| $('#' + l_newCell + ':has(".ally")').val() != undefined
|| $('#' + l_newCell + ':has(".obstacle")').val() != undefined)
{
direction = "left";
setCharDynamics(controlsPlayerChar);
return false;
}
$('#' + l_newCell).append($('#' + controlsPlayerChar));
$('#' + l_oldCell + ' ' + '#' + controlsPlayerChar).remove();
// set char direction to 'left' and set next footstep
setDirection('left');
setFootstep(footstep);
setCharDynamics(controlsPlayerChar);
});
var up = document.getElementById('up');
up.addEventListener("touchstart", function(e){
if(controlsPlayerChar == '')
{
return false;
}
var u_oldCell = $('#' + controlsPlayerChar).parent().attr('id');
var u_xy = u_oldCell.split('_');
var u_x = u_xy[0];
var u_y = u_xy[1];
if(u_x == 1)
{
direction = "up";
setCharDynamics(controlsPlayerChar);
return false;
}
var u_newCell = (parseInt(u_x) - 1) + '_' + u_y;
// validate if next cell is empty
if($('#' + u_newCell + ':has(".shadow")').val() != undefined
|| $('#' + u_newCell + ':has(".ally")').val() != undefined
|| $('#' + u_newCell + ':has(".obstacle")').val() != undefined)
{
direction = "up";
setCharDynamics(controlsPlayerChar);
return false;
}
$('#' + u_newCell).append($('#' + controlsPlayerChar));
$('#' + u_oldCell + ' ' + '#' + controlsPlayerChar).remove();
// set char direction to 'up' and set next footstep
setDirection('up');
setFootstep(footstep);
setCharDynamics(controlsPlayerChar);
});
var down = document.getElementById('down');
down.addEventListener("touchstart", function(e){
if(controlsPlayerChar == '')
{
return false;
}
var d_oldCell = $('#' + controlsPlayerChar).parent().attr('id');
var d_xy = d_oldCell.split('_');
var d_x = d_xy[0];
var d_y = d_xy[1];
if(d_x == rows)
{
direction = "down";
setCharDynamics(controlsPlayerChar);
return false;
}
var d_newCell = (parseInt(d_x) + 1) + '_' + d_y;
// validate if next cell is empty
if($('#' + d_newCell + ':has(".shadow")').val() != undefined
|| $('#' + d_newCell + ':has(".ally")').val() != undefined
|| $('#' + d_newCell + ':has(".obstacle")').val() != undefined)
{
direction = "down";
setCharDynamics(controlsPlayerChar);
return false;
}
$('#' + d_newCell).append($('#' + controlsPlayerChar));
$('#' + d_oldCell + ' ' + '#' + controlsPlayerChar).remove();
// set char direction to 'down' and set next footstep
setDirection('down');
setFootstep(footstep);
setCharDynamics(controlsPlayerChar);
});
var right = document.getElementById('right');
right.addEventListener("touchstart", function(e){
if(controlsPlayerChar == '')
{
return false;
}
var r_oldCell = $('#' + controlsPlayerChar).parent().attr('id');
var r_xy = r_oldCell.split('_');
var r_x = r_xy[0];
var r_y = r_xy[1];
if(r_y == cols)
{
direction = "right";
setCharDynamics(controlsPlayerChar);
return false;
}
var r_newCell = r_x + '_' + (parseInt(r_y) + 1);
// validate if next cell is empty
if($('#' + r_newCell + ':has(".shadow")').val() != undefined
|| $('#' + r_newCell + ':has(".ally")').val() != undefined
|| $('#' + r_newCell + ':has(".obstacle")').val() != undefined)
{
direction = "right";
setCharDynamics(controlsPlayerChar);
return false;
}
$('#' + r_newCell).append($('#' + controlsPlayerChar));
$('#' + r_oldCell + ' ' + '#' + controlsPlayerChar).remove();
// set char direction to 'right' and set next footstep
setDirection('right');
setFootstep(footstep);
setCharDynamics(controlsPlayerChar);
});
}
Please let me know if you think anything is amiss with regards to above script. The way I add the touchstart event is the same in other areas of my script when e.g to launch an attack or launch an options menu for instance.
Seems that this is tap highlighting.
You can try to disable this effect applying -webkit-tap-highlight-color CSS property on your controls or disable this in all elements using * selector.
For example:
.someelement {
-webkit-tap-highlight-color: transparent;
}
We've ran into this issue when using translate3d transformations.
We fixed it by setting
* { -webkit-transform: translate3d(0,0,0,); }
so that every element is initialized for the 3d space
First of all, make sure you are calling preventDefault() on the event. I've noticed that if you are targeting mouse events as well, they can fire on touch. Otherwise, I use a slightly different method of disabling touch highlighting. Try:
-webkit-tap-highlight-color: rgba(0,0,0,0);
In the css for your button.
Related
I am working on a web application in Visual Studio using visual basic and master pages. I have 10 textbox fields on a child page where I would like to emulate the iPhone password entry (ie. show the character entered for a short period of time then change that character to a bullet). This is the definition of one of the text box controls:
<asp:TextBox ID="txtMID01" runat="server" Width="200" MaxLength="9"></asp:TextBox>
At the bottom of the page where the above control is defined, I have the following:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="lib/jQuery.dPassword.js"></script>
<script type="text/javascript">
$(function () {
var textbox01 = $("[id$=txtMID01]");
alert(textbox01.attr("id"));
$("[id$=txtMID01]").dPassword()
});
</script>
When the page loads, the alert displays MainContent_txtMID01 which is the ID of the control preceeded with the name of the content place holder.
The following is the contents of lib/jQuery.dPassword.js (which I found on the internet):
(function ($) {
$.fn.dPassword = function (options) {
var defaults = {
interval: 200,
duration: 3000,
replacement: '%u25CF',
// prefix: 'password_',
prefix: 'MainContent_',
debug: false
}
var opts = $.extend(defaults, options);
var checker = new Array();
var timer = new Array();
$(this).each(function () {
if (opts.debug) console.log('init [' + $(this).attr('id') + ']');
// get original password tag values
var name = $(this).attr('name');
var id = $(this).attr('id');
var cssclass = $(this).attr('class');
var style = $(this).attr('style');
var size = $(this).attr('size');
var maxlength = $(this).attr('maxlength');
var disabled = $(this).attr('disabled');
var tabindex = $(this).attr('tabindex');
var accesskey = $(this).attr('accesskey');
var value = $(this).attr('value');
// set timers
checker.push(id);
timer.push(id);
// hide field
$(this).hide();
// add debug span
if (opts.debug) {
$(this).after('<span id="debug_' + opts.prefix + name + '" style="color: #f00;"></span>');
}
// add new text field
$(this).after(' <input name="' + (opts.prefix + name) + '" ' +
'id="' + (opts.prefix + id) + '" ' +
'type="text" ' +
'value="' + value + '" ' +
(cssclass != '' ? 'class="' + cssclass + '"' : '') +
(style != '' ? 'style="' + style + '"' : '') +
(size != '' ? 'size="' + size + '"' : '') +
(maxlength != -1 ? 'maxlength="' + maxlength + '"' : '') +
// (disabled != '' ? 'disabled="' + disabled + '"' : '') +
(tabindex != '' ? 'tabindex="' + tabindex + '"' : '') +
(accesskey != undefined ? 'accesskey="' + accesskey + '"' : '') +
'autocomplete="off" />');
// change label
$('label[for=' + id + ']').attr('for', opts.prefix + id);
// disable tabindex
$(this).attr('tabindex', '');
// disable accesskey
$(this).attr('accesskey', '');
// bind event
$('#' + opts.prefix + id).bind('focus', function (event) {
if (opts.debug) console.log('event: focus [' + getId($(this).attr('id')) + ']');
clearTimeout(checker[getId($(this).attr('id'))]);
checker[getId($(this).attr('id'))] = setTimeout("check('" + getId($(this).attr('id')) + "', '')", opts.interval);
});
$('#' + opts.prefix + id).bind('blur', function (event) {
if (opts.debug) console.log('event: blur [' + getId($(this).attr('id')) + ']');
clearTimeout(checker[getId($(this).attr('id'))]);
});
setTimeout("check('" + id + "', '', true);", opts.interval);
});
getId = function (id) {
var pattern = opts.prefix + '(.*)';
var regex = new RegExp(pattern);
regex.exec(id);
id = RegExp.$1;
return id;
}
setPassword = function (id, str) {
if (opts.debug) console.log('setPassword: [' + id + ']');
var tmp = '';
for (i = 0; i < str.length; i++) {
if (str.charAt(i) == unescape(opts.replacement)) {
tmp = tmp + $('#' + id).val().charAt(i);
}
else {
tmp = tmp + str.charAt(i);
}
}
$('#' + id).val(tmp);
}
check = function (id, oldValue, initialCall) {
if (opts.debug) console.log('check: [' + id + ']');
var bullets = $('#' + opts.prefix + id).val();
if (oldValue != bullets) {
setPassword(id, bullets);
if (bullets.length > 1) {
var tmp = '';
for (i = 0; i < bullets.length - 1; i++) {
tmp = tmp + unescape(opts.replacement);
}
tmp = tmp + bullets.charAt(bullets.length - 1);
$('#' + opts.prefix + id).val(tmp);
}
else {
}
clearTimeout(timer[id]);
timer[id] = setTimeout("convertLastChar('" + id + "')", opts.duration);
}
if (opts.debug) {
$('#debug_' + opts.prefix + id).text($('#' + id).val());
}
if (!initialCall) {
checker[id] = setTimeout("check('" + id + "', '" + $('#' + opts.prefix + id).val() + "', false)", opts.interval);
}
}
convertLastChar = function (id) {
if ($('#' + opts.prefix + id).val() != '') {
var tmp = '';
for (i = 0; i < $('#' + opts.prefix + id).val().length; i++) {
tmp = tmp + unescape(opts.replacement);
}
$('#' + opts.prefix + id).val(tmp);
}
}
};
})(jQuery);
When I execute my code, the code behind populates the value of the textbox with "123456789" and when the page gets rendered, all the characters have been changed to bullets, which is correct. The problem I am having is that the textbox has been disabled so I can not edit the data in the textbox.
I removed (by commenting out) the references to the disabled attribute but the control still gets rendered as disabled.
As a side note, the code that I found on the internet was originally designed to work with a textbox with a type of password but when I set the TextMode to password, not only does the control get rendered as disabled, but the field gets rendered with no value so I left the TextMode as SingleLine.
Any suggestions or assistance is greatly appreciated.
Thanks!
As far as I know, it is not possible to have it so that while you type a password, the last letter is visible for a second and then turns into a bullet or star.
However what you can do is as the user types in password, with a delay of lets say 500ms store the string the user has typed in so far into some variable and replace the content of the password field or the text field with stars or black bullets. This will give you what you are looking for.
I've been working on this script that I am using with a WordPress plugin I wrote for our blogs at work. I'm stripping it down to make it a pure jQuery plugin but most of the questions I've seen where for getting the plugin to work like this:
$('.some-target').cta();
Whereas I want to write it so that the user can do something like:
cta();
or
$.cta
I'm not really getting clear answers or seeing many guides covering this, or really if it's possible. In the end I want it to work like it's original iteration for WP, but as a stand alone jQuery plugin for static sites:
cta({
text: "Some Text",
icon: "Some-icon.jpg",
dist: 50
});
Here is the original code:
jQuery(document).ready(function($){
cta = function(o) {
o = o || {};
var bgColor = o.bgColor;
var url = o.url;
var text = o.text;
var icon = o.icon;
var buttonText = o.buttonText;
var target = o.target;
var dist = o.dist;
if((o.icon != null) || o.icon == "" ) {
jQuery('body').append(
'<div class="cta-popup-wrapper with-icon"><div class="cta-popup"><span class="close-trigger">X</span><img class="cta-icon" src="' + icon + '" alt="Call to Action Icon"><p>' + text + '</p><a class="cta-button" style="background-color:' + bgColor + ';" href="' + url + '">' + buttonText + '</a></div></div>'
);
} else {
jQuery('body').append(
'<div class="cta-popup-wrapper without-icon"><div class="cta-popup"><span class="close-trigger">X</span><p>' + text + '</p><a class="cta-button" style="background-color:' + bgColor + ';" href="' + url + '">' + buttonText + '</a></div></div>'
);
}
if(target != null) {
var t = $(target);
if(t.length) {
$(window).scroll(function() {
var hT = t.offset().top,
hH = t.outerHeight(),
wH = $(window).height(),
wS = $(this).scrollTop();
if (wS > (hT+hH-wH)){
$('.cta-popup-wrapper').addClass('shown');
} else {
$('.cta-popup-wrapper').removeClass('shown');
}
});
}
} else {
if((dist != null) && (dist > 0)) {
var b = $('body').innerHeight();
dist = dist / 100;
var trigger = b * dist;
$(window).scroll(function() {
var wS = $(this).scrollTop();
if (wS > trigger){
$('.cta-popup-wrapper').addClass('shown');
} else {
$('.cta-popup-wrapper').removeClass('shown');
}
});
}
}
}
});
I am currently working on a project where I am placing an svg text element wrapped in a group on a template. I need the user to both drag the element around (which I have working) and move SELECTED element via arrow keys. The code below is what I have been working on for a while now and the element seems to jump right and down by several pixels at a time. Something is just not right. Can anyone help me with this? Thanks!
function drag(r) {
r.drag(move, start, stop);
}
var move = function() {
this.attr({style:'cursor: grabbing;'});
}
var start = function() {
}
var stop = function() {
this.attr({style:'cursor: pointer;'});
xyc(this);
}
function xyc(svg){
var bb = svg.getBBox();
console.log('New: x: ' + bb.x + ' y: '+ bb.y);
keymove(svg,bb.x,bb.y);
}
function keymove(g,bx,by) {
console.log('New: x: ' + bx + ' y: '+ by);
$(document).keydown(function(e){
e.preventDefault();
if(e.keyCode == 39) {//right
g.attr('kx', bx+=1);
g.attr('ky', by);
g.attr({transform:'translate('+ g.attr('kx') + ',' + g.attr('ky') + ')'});
xyc(g);
}else if(e.keyCode == 37) {//left
g.attr('kx', bx-=1);
g.attr('ky', by);
g.attr({transform:'translate('+ g.attr('kx') + ',' + g.attr('ky') + ')'});
xyc(g);
}
else{
return;
}
});
}
i am making a client for my node.js irc bot and want to implement tab complete but the regex in the following code returns null for no reason. i have included what's logged as comments next to the console.log statement.
what is tab complete: i type "mic" and press tab, it the automatically completes it to "michael" because he is a user in the channel.
tabStart = false;
$("#textbox").keydown(function (e) {
if (!$(this).val().length) return;
if (e.keyCode === 9) {
e.preventDefault();
var text = $(this).val();
console.log('text: ' + text);// mic
var index = text.lastIndexOf(" ");
console.log('index: ' + index);// -1
if (!tabStart) {
tabStart = index > -1 ? text.substr(index + 1) : text;
var current = '';
} else {
var current = index > -1 ? text.substr(index + 1) : text;
}
console.log('tabStart: ' + tabStart);// mic
console.log('current: ' + current);//
var active = $("#tabs").tabs("option", "active");
var channel = $("#tabs ul>li a").eq(active).attr("href");
console.log('channel: ' + channel);// #debug
var users = $(channel + " .user-list li");
var regex = new RegExp("^" + tabStart + ".*", "i");
console.log('regex: ' + regex);// /^mic.*/i
for (var i = 0; i < users.length; ++i) {
var user = $(users[i]).text();
console.log('user: ' + user);// michael
var match = user.match(regex);
console.log('match: ' + match);// null
if (match) {
var newText = (index > -1 ? text.substr(0, index + 1) : "") + user;
console.log('newText: ' + newText);
$(this).val(newText);
break;
}
}
} else {
tabStart = false;
}
});
as i said, i can't seem to find an explanation for this because i tried the following in the javascript console and it works
var regex = new RegExp("^mic.*", "i");"michael".match(regex);
It looks like you have an issue with getting the correct text from users. Since I don't know your actual HTML, I created a CodePen and commented out some of the channel lines and added users as a typical array. Doing that, your regex works fine.
Here is the codePen in action.
figured out the problem. user was wrapped in .
I have inherited a website! which was designed to work in IE and only IE it seems.. I've now been asked to make the site run in Firefox. I've fixed most of the bugs without any problems but this one has me stumped.
setTimeout(fDelayedFunc, 1000);
This line of Javascript, works fine in IE but in Firefox the function fDelayedFunc never fires. I've removed the setTimeout and the function wrapper and tried running the code as part of the main function. This works without any problems at all.
There is alot of code involved but here's the main but I'm having trouble with. If you'd like to see anymore of the code please let me know.
setTimeout(fDelayedFunc, 0);
//Save the current text box value
var vCurrentTBValue = vJQElement.val();
function fDelayedFunc() {
if (vJQElement.val() == vCurrentTBValue) {
alert("test");
//Get position list box should appear in
var vTop = vJQElement.position().top + 25;
var vLeft = vJQElement.position().left;
//Had to put a special case in for account due to the position co-ords being wrong. This is due to a css error
if (vHiddenFieldToWriteTo == "#ctl00_ContentPlaceHolder1_hfAccountCode") {
vTop = vJQElement.position().top + 58;
vLeft = vJQElement.position().left + 200;
}
else {
vTop = vJQElement.position().top + 25;
vLeft = vJQElement.position().left;
}
//Create div element
var vDivElement = $("<div id='divSearchBox' style='position:absolute; top:" + vTop + ";left:" + vLeft + "; z-index: 40000;'></div>");
//Create list box
var vListBox = $("<select id='lbResults' tabIndex='" + vJQElement.attr("tabIndex") + "' size='4' style='height:400px;'></select>");
//Bind a function to the list box which will select the item via either tab or enter
vListBox.bind("keydown", function() {
//Check if tab or enter has been pressed
if (event.keyCode == 9 || event.keyCode == 13) {
//Set hidden value to the selected items code
$(vHiddenFieldToWriteTo).val($(vListBox.find(":selected")).val());
//Create postback
$('#ctl00_ContentPlaceHolder1_wizNewConsignment_btnRefresh').click();
}
//Check if the up arrow has been pressed at the top of the listbox
else if (event.keyCode == 38 && $(vListBox.find(":selected")).val() == $(vListBox.find(":first")).val()) {
//Focus back on the search box
vElement.focus();
}
}).bind("dblclick", function() {
//Set hidden value to the selected items code
$(vHiddenFieldToWriteTo).val($(vListBox.find(":selected")).val());
//Create postback
$('#ctl00_ContentPlaceHolder1_wizNewConsignment_btnRefresh').click();
});
//Get search field
var vSearchText = vJQElement.val();
var vDepotID = $("#ctl00_ContentPlaceHolder1_wizNewConsignment_hfDepotID").val();
var vCustomerID = $("#ctl00_ContentPlaceHolder1_wizNewConsignment_hfCustomerID").val();
var vCountryID = $("#ctl00_ContentPlaceHolder1_wizNewConsignment_hfCountryID").val();
var vConsignee = vJQElement.attr("boolConsignee");
//Set a loading image in place until call completed
vJQElement.css("backgroundImage", "url(images/small-loader.gif)");
vJQElement.css("backgroundRepeat", "no-repeat");
vJQElement.css("backgroundPosition", "right");
//Make AJAX call
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "NewConsignment.asmx/fGetAddressesAndIDs",
data: "{'strSearchText' : '" + vSearchText + "', 'intDepotID' : '" + vDepotID + "', 'intCustomerID' : '" + vCustomerID + "', 'intCountryID' : '" + vCountryID + "', 'boolConsignee' : '" + vConsignee + "'}",
dataType: "json",
success: function fGetAddressesAndIDsResult(GetAddressesAndIDsResult) {
//Make sure there are results
if (GetAddressesAndIDsResult != null && GetAddressesAndIDsResult != "") {
var vNumberOfResults = 0;
var vNumberOfLearntAddresses = 0;
var vLearntAddressUniqueID = "";
//Try to get results (first call will work on Linux and catch will work on Windows)
try {
//Check array exists (if this fails will go to catch)
if (GetAddressesAndIDsResult.d.length > 0) {
//Loop through the results
$.each(GetAddressesAndIDsResult.d, function() {
//Check for results
if (this.length > 0) {
//Evaluate JSON
var vAddress = eval("(" + this + ")");
//Create list item
var vOption = $("<option class='AddressOption' value='" + vAddress.uniqueID + "'>" + vAddress.briefDescription + "</option>");
//Find out number of learnt addresses
if (vAddress.uniqueID.indexOf("ConLA") != -1) {
vNumberOfLearntAddresses++;
vLearntAddressUniqueID = vAddress.uniqueID;
}
//Add list item to list box
vListBox.append(vOption);
//Mark result added
vNumberOfResults++;
}
});
}
}
catch (err) {
//Loop through the results
$.each(GetAddressesAndIDsResult, function() {
//Check for results
if (this.length > 0) {
//Evaluate JSON
var vAddress = eval("(" + this + ")");
//Create list item
var vOption = $("<option class='AddressOption' value='" + vAddress.uniqueID + "'>" + vAddress.briefDescription + "</option>");
//Find out number of learnt addresses
if (vAddress.uniqueID.indexOf("ConLA") != -1) {
vNumberOfLearntAddresses++;
vLearntAddressUniqueID = vAddress.uniqueID;
}
//Add list item to list box
vListBox.append(vOption);
//Mark result added
vNumberOfResults++;
}
});
}
//Check if only 1 learnt address was found
if (vNumberOfLearntAddresses == 1) {
//Auto select this address
//Set hidden value to the selected items code
$(vHiddenFieldToWriteTo).val(vLearntAddressUniqueID);
//Create postback
$('#ctl00_ContentPlaceHolder1_wizNewConsignment_btnRefresh').click();
}
//Add list box to div
vDivElement.append(vListBox);
//Check if any results exist in div
if (vNumberOfResults != 0) {
//Append div to page
$("body").append(vDivElement);
//Auto select first item
vListBox.find(".AddressOption:first").attr("selected", "true");
}
}
//Hide loading image
vJQElement.css("backgroundImage", "none");
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
//Inform user of error
alert("An error occured, please try again");
//Hide loading image
vJQElement.css("backgroundImage", "none");
}
});
}
}
Try this:
setTimeout(function() { fDelayedFunc(); }, 0);
I took setTimeout(function () {function1();}, 1500) out from the addEventListener("load", () => {code})
it worked for me inside Firefox
try this : setTimeout('fDelayedFunc()', 0);