I'm attempting to implement the float label pattern (https://webdesign.tutsplus.com/articles/implementing-the-float-label-form-pattern--webdesign-16407) for my WooCommerce forms.
The checkout from is here - https://dev.joshkern.co/checkout/.
You'll first need to add a product/service from here - https://dev.joshkern.co/wordpress-maintenance/. You'll see the form isn't working as it should. What am I missing?
This is my javascript:
(function($) {
$(document).ready(function(){
// Test for placeholder support
$.support.placeholder = (function(){
var i = document.createElement('input');
return 'placeholder' in i;
})();
// Hide labels on page load if placeholders are supported
if ($.support.placeholder) {
$('.woocommerce form .form-row').each(function(){
$(this).addClass('js-hide-label');
});
$('.woocommerce form .form-row').find('input, textarea').on('keyup blur focus', function(e){
// Cache our selectors
var $this = $(this),
$parent = $this.parent();
// Add or remove classes
if (e.type == 'keyup') {
if ($this.val() == '') {
$parent.addClass('js-hide-label');
}
else {
$parent.removeClass('js-hide-label');
}
}
else if (e.type == 'blur') {
if( $this.val() == '' ) {
$parent.addClass('js-hide-label');
}
else {
$parent.removeClass('js-hide-label').addClass('js-unhighlight-label');
}
}
else if (e.type == 'focus') {
if( $this.val() !== '' ) {
$parent.removeClass('js-unhighlight-label');
}
}
});
}
});
})(jQuery);
Related
my javascript file for multiple email(multiple_emails.js plugin) is working fine with ng serve my code :
(function( $ ){
$.fn.multiple_emails = function(options) {
// Default options
var defaults = {
checkDupEmail: true,
theme: "Bootstrap",
position: "top",
invalid:"Invalid Email Id"
};
// Merge send options with defaults
var settings = $.extend( {}, defaults, options );
var deleteIconHTML = "";
if (settings.theme.toLowerCase() == "Bootstrap".toLowerCase())
{
deleteIconHTML = '<span class="glyphicon glyphicon-remove"></span>';
}
else if (settings.theme.toLowerCase() == "SemanticUI".toLowerCase() || settings.theme.toLowerCase() == "Semantic-UI".toLowerCase() || settings.theme.toLowerCase() == "Semantic UI".toLowerCase()) {
deleteIconHTML = '<i class="remove icon"></i>';
}
else if (settings.theme.toLowerCase() == "Basic".toLowerCase()) {
//Default which you should use if you don't use Bootstrap, SemanticUI, or other CSS frameworks
deleteIconHTML = '<i class="basicdeleteicon">Remove</i>';
}
return this.each(function() {
var to_id = this.id;
var orig_id=to_id;
console.log(to_id);
var arr = to_id.split('_');
to_id = arr[1];
console.log("to_id",to_id);
setTimeout(function(){
console.log($('.licls'+to_id).length);
if($('.licls'+to_id).length > 4){
$('#input_'+to_id).css('display','none');
}else {
$('#input_'+to_id).css('display','block');
}
},200);
//$orig refers to the input HTML node
var $orig = $(this);
var $list = $('<ul class="multiple_emails-ul" id=ul_'+to_id+' />'); // create html elements - list of email addresses as unordered list
console.log($(this).val());
if ($(this).val() != '' && IsJsonString($(this).val())) {
$.each(jQuery.parseJSON($(this).val()), function( index, val ) {
$list.append($('<li class="multiple_emails-email licls'+to_id+'"><span class="email_name" data-email="' + val.toLowerCase() + '">' + val + '</span></li>')
.prepend($(deleteIconHTML)
.click(function(e) { $(this).parent().remove(); refresh_emails(); e.preventDefault(); })
)
);
});
}
var $input = $('<input type="text" class="multiple_emails-input text-left" id= input_'+to_id+' />').on('keyup', function(e) { // input
console.log($(this).attr('id'));
$(this).removeClass('multiple_emails-error');
$('#'+orig_id).parent().find("label").remove();
var input_length = $(this).val().length;
var keynum;
if(window.event){ // IE
keynum = e.keyCode;
}
else if(e.which){ // Netscape/Firefox/Opera
keynum = e.which;
}
//if(event.which == 8 && input_length == 0) { $list.find('li').last().remove(); } //Removes last item on backspace with no input
// Supported key press is tab, enter, space or comma, there is no support for semi-colon since the keyCode differs in various browsers
if(keynum == 9 || keynum == 32 || keynum == 188) {
display_email($(this), settings.checkDupEmail);
}
else if (keynum == 13) {
if($('.licls'+to_id).length > 4){
$('#input_'+to_id).css('display','none');
}else {
$('#input_'+to_id).css('display','block');
}
display_email($(this), settings.checkDupEmail);
//Prevents enter key default
//This is to prevent the form from submitting with the submit button
//when you press enter in the email textbox
e.preventDefault();
}
}).on('blur', function(event){
if($('.licls'+to_id).length > 4){
$('#input_'+to_id).css('display','none');
}else {
$('#input_'+to_id).css('display','block');
}
$('#'+orig_id).parent().find("label").remove();
if ($(this).val() != '') { display_email($(this), settings.checkDupEmail); }
});
var $container = $('<div class="multiple_emails-container contnr_'+to_id+'" />').click(function() { $input.focus(); } ); // container div
// insert elements into DOM
if (settings.position.toLowerCase() === "top")
$container.append($list).append($input).insertAfter($(this));
else
$container.append($input).append($list).insertBefore($(this));
/*
t is the text input device.
Value of the input could be a long line of copy-pasted emails, not just a single email.
As such, the string is tokenized, with each token validated individually.
If the dupEmailCheck variable is set to true, scans for duplicate emails, and invalidates input if found.
Otherwise allows emails to have duplicated values if false.
*/
function display_email(t, dupEmailCheck) {
console.log(t.attr('id'));
//Remove space, comma and semi-colon from beginning and end of string
//Does not remove inside the string as the email will need to be tokenized using space, comma and semi-colon
var arr = t.val().trim().replace(/^,|,$/g , '').replace(/^;|;$/g , '');
//Remove the double quote
arr = arr.replace(/"/g,"");
//Split the string into an array, with the space, comma, and semi-colon as the separator
arr = arr.split(/[\s,;]+/);
var errorEmails = new Array(); //New array to contain the errors
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))#((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
for (var i = 0; i < arr.length; i++) {
var res_arr=JSON.parse($orig.val().toLowerCase().split(','))
//Check if the email is already added, only if dupEmailCheck is set to true
if ( dupEmailCheck === true && res_arr.indexOf(arr[i].toLowerCase()) != -1) {
if (arr[i] && arr[i].length > 0) {
new function () {
var existingElement = $list.find('.email_name[data-email=' + arr[i].toLowerCase().replace('.', '\\.').replace('#', '\\#') + ']');
existingElement.css('font-weight', 'bold');
setTimeout(function() { existingElement.css('font-weight', ''); }, 1500);
}(); // Use a IIFE function to create a new scope so existingElement won't be overriden
}
}
else if ( pattern.test(arr[i]) == true && res_arr.indexOf(arr[i].toLowerCase()) == -1) {
if($('#ulcls'+t.attr('id')).length < 4) {
$list.append($('<li class="multiple_emails-email licls'+to_id+'"><span class="email_name" data-email="' + arr[i].toLowerCase() + '">' + arr[i] + '</span></li>')
.prepend($(deleteIconHTML)
.click(function(e) { $(this).parent().remove(); refresh_emails(); e.preventDefault(); })
)
);
}
}
else
errorEmails.push(arr[i]);
}
// If erroneous emails found, or if duplicate email found
if(errorEmails.length > 0) {
t.val(errorEmails.join("; ")).addClass('multiple_emails-error');
t.after('<label for='+orig_id+' style="color:#cc5965;">'+settings.invalid+'</label>');
}else {
$('#'+orig_id).parent().find("label").remove();
t.val("");
}
refresh_emails ();
}
function refresh_emails () {
var emails = new Array();
var container = $orig.siblings('.multiple_emails-container');
container.find('.multiple_emails-email span.email_name').each(function() { emails.push($(this).html()); });
$orig.val(JSON.stringify(emails)).trigger('change');
if($('.licls'+to_id).length > 4){
$('#input_'+to_id).css('display','none');
}else {
$('#input_'+to_id).css('display','block');
}
}
function IsJsonString(str) {
try { JSON.parse(str); }
catch (e) { return false; }
return true;
}
$(document).ready(function(){
$('#input_'+to_id).on("cut copy paste",function(e) {
e.preventDefault();
});
});
return $(this).hide();
});
};
})(jQuery);
But when i compile it with ng build --prod it's gives TypeError: $(...).multiple_emails is not a function , if it's not working correctly any other tool to convert from JavaScript to typescript ?
i had convert js into typesript using online compiler but nothing happened.
solved!!!!
finally i figure out the problem. it is in angular-cli.json.when i place my multiple_email.js after jquery-3.1.1.min.js,jquery.validate.min.js then it works like charm...!!! #rajesh thanks
I'm looking for the way to translate this block of code from jQuery to pure javascript. Is it possible?
jQuery(".menu2").each(function(){
$menu = jQuery(this);
$menu.find("li").unbind('mouseenter mouseleave').filter(".deeper").children("span.separator").addClass("parent");
$menu.find("li.deeper>a.parent, li.deeper>span.separator").unbind('click').bind('click', function(e) {
e.preventDefault();
jQuery(this).parent("li").children("ul").animate({height: 'toggle'}, 300, "jswing");
});
$menu.find("li a.parent > span.linker").click(function(){
if((typeof jQuery(this).parent().attr("href") != 'undefined') && jQuery(this).parent().attr("href") != "#"){
jQuery(this).parent().unbind('click');
myLink = jQuery(this).parent().attr("href");
window.location.href = myLink;
}
});
}
Thanks!
Of course it's possible. Whether it's a good idea or not is debatable, but here...
[].forEach.call(document.querySelectorAll(".menu2"),function(menu){
[].forEach.call(menu.getElementsByTagName("li"),function(li) {
li.__events = li.__events || {};
if( li.__events.mouseenter) {
li.removeEventListener('mouseenter',li.__events.mouseenter);
delete li.__events.mouseenter;
}
if( li.__events.mouseleave) {
li.removeEventListener('mouseleave',li.__events.mouseleave);
delete li.__events.mouseleave;
}
if( li.className.match(/\bdeeper\b/)) {
[].forEach.call(li.querySelectorAll("span.separator"),function(span) {
if( !span.className.match(/\bparent\b/)) span.className += " match";
});
}
});
[].forEach.call(menu.querySelectorAll("li.deeper>a.parent, li.deeper>span.separator"),function(elem) {
elem.__events = elem.__events || {};
if( elem.__events.click) {
elem.removeEventListener('click',elem.__events.click);
delete elem.__events.click;
}
elem.addEventListener('click',elem.__events.click = function(e) {
[].forEach.call(this.parentNode.getElementsByTagName('ul'),function(ul) {
if( ul.style.height == "auto") ul.style.height = "0px";
else ul.style.height = "auto";
// TODO: Implement animation here
});
return false;
},false);
});
[].forEach.call(menu.querySelectorAll("li a.parent>span.linker"),function(elem) {
elem.__events = elem.__events || {};
if( elem.__events.click) {
elem.removeEventListener('click',elem.__events.click);
delete elem.__events.click;
}
elem.addEventListener('click',elem.__events.click = function(e) {
if( this.parentNode.getAttribute("href") != "#") {
window.location.href = this.parentNode.href;
}
return false;
},false);
});
});
... I think it's fairly obvious why people use jQuery. Of course, I would have my own toolbox to make a lot of this code easier to manage ;)
Placeholder is not working in below IE10 browsers, meanwhile i wrote following code it is working fine.
But problem is in password field it shows dots instead of placeholder text. Please find the attached screen shot.
Here is my code, could you please help is there any solution for fixing the password field placeholder visible.
//Default text in login page.
(function ($) {
$.support.placeholder = ('placeholder' in document.createElement('input'));
})(jQuery);
//fix for IE7 and IE8
$(function () {
if (!$.support.placeholder) {
$("[placeholder]").focus(function () {
if ($(this).val() == $(this).attr("placeholder")) $(this).val("");
}).blur(function () {
if ($(this).val() == "") $(this).val($(this).attr("placeholder"));
}).blur();
$("[placeholder]").parents("login").submit(function () {
$(this).find('[placeholder]').each(function() {
if ($(this).val() == $(this).attr("placeholder")) {
$(this).val("");
}
});
});
}
});![enter image description here][1]
Use this below, it will help you
$(function () {
var input = document.createElement("input");
if (('placeholder' in input) == false) {
$('[placeholder]').focus(function () {
var i = $(this);
if (i.val() == i.attr('placeholder')) {
i.val('').removeClass('placeholder');
if (i.hasClass('password')) {
i.removeClass('password');
this.type = 'password';
}
}
}).blur(function () {
var i = $(this);
if (i.val() == '' || i.val() == i.attr('placeholder')) {
if (this.type == 'password') {
i.addClass('password');
this.type = 'text';
}
i.addClass('placeholder').val(i.attr('placeholder'));
}
}).blur().parents('form').submit(function () {
$(this).find('[placeholder]').each(function () {
var i = $(this);
if (i.val() == i.attr('placeholder'))
i.val('');
})
});
}
});
How can I prevent my form from submitting until all required fields are populated? Required fields could be input, select, etc.
Below is my current code which is not working. Basically after I click on the submit button I would like to iterate through each field in the form which has tag='required' and if all fields are populated/selected then allow form submit.
Thanks.
$("#submitButton").click(function (e) {
var submit = false;
var count = 0;
$('#Form input, #Form select').each(function () {
var id = $(this).attr('id');
var value = $('#' + id).val();
var tagValue = $('#' + id).attr('tag');
var isDisabled = $('#' + id).is(':disabled');
if (isDisabled == false) {
if ($('#' + id).is(':visible')) {
if (tagValue == 'required') {
if (id == 'email') {
validateEmail('#' + id);
}
if (id == 'phone') {
validatePhone('#' + id);
}
if ($('#' + id).hasClass("currency")) {
validateCurrency('#' + id);
}
if ($('#' + id).is('select')) {
if (value == '' || value == 'Unknown' || value == 'unassigned' || value == null) {
$('#' + id).css({
'border': '1px solid #F70D1A'
});
}
}
else if (value == "") {
$('#' + id).css({
'border': '1px solid #F70D1A'
});
}
if (value == '' || value == 'Unknown' || value == 'unassigned' || value == null) {
submit = false;
} else {
submit = true;
}
}
}
}
});
if (!submit) {
e.preventDefault();
}
});
Rather than attaching this event to the button click, you should attach it to the form on submit:
$('#Form').on('submit', function (e) {
//-- your current code should work fine, put it here
});
I went ahead and cleaned up your method:
$("#Form").on('submit', function (e) {
var submit = true;
//-- use find+filter to reduce the set of matched elements
$(this).find('input, select').filter('[tag="required"]:visible:enabled').each(function () {
var $this = $(this),
value = $this.val();
//-- switch for unique flags
switch ($this.attr('id')) {
case 'email': validateEmail($this); break;
case 'phone': validatePhone($this); break;
}
//-- continue parsing non-unique flags
if ($this.hasClass('currency')) validateCurrency($this);
if (!value || value === 'Unknown' || value === 'unassigned') {
$this.css('border', '1px solid #F70D1A');
submit = false;
}
});
if (!submit) {
e.preventDefault();
}
});
Things to note:
I removed all of the unnecessary ID-based lookups. This is a huge performance hit, and should be reduced to a single $(this) lookup which you should reuse.
I am currently passing $this to each validate method, so they will have to be updated accordingly.
Rather than iterating through all select/input fields, I reduced the matched elements first, cutting down on unnecessary code.
I simplified your logic to the best of my understanding based on the code provided.
I switched the method used on the submit flag. It now starts out as valid and will be set to false if any item fails the check.
$('#Form').on('submit', function (e) {
$.each(this.find("[tag='required']"),function(i,item)
{
validation logic goes here.
....
}
)});
I found following function to enable placeholder like effect on browsers like IE6-9.
The problem is placeholder appears after first-time focusing. There is no initial value. Input boxes are just blank after page loading.
And another thing is, as on tutorial I created .placeholder class and set color to grey. It sets inputs color to light grey and doesn't change to black while user types.
var isInputSupported = 'placeholder' in document.createElement('input');
var isTextareaSupported = 'placeholder' in document.createElement('textarea');
if (!isInputSupported || !isTextareaSupported) {
$('[placeholder]').focus(function () {
var input = $(this);
if (input.val() == input.attr('placeholder') && input.data('placeholder')) {
input.val('');
input.removeClass('placeholder');
}
}).blur(function () {
var input = $(this);
if (input.val() == '') {
input.addClass('placeholder');
input.val(input.attr('placeholder'));
input.data('placeholder', true);
} else {
input.data('placeholder', false);
}
}).blur().parents('form').submit(function () {
$(this).find('[placeholder]').each(function () {
var input = $(this);
if (input.val() == input.attr('placeholder') && input.data('placeholder')) {
input.val('');
}
})
});
}
Any suggestions?
To address the problem of the placeholders not showing up initially, you need to initialize each of them when the page loads, something like this:
$('[placeholder]').each(function(){
var $this = $(this);
if($this.val() == ''){
$this.val($this.data('placeholder')).addClass('placeholder');
}
});
The problem with the text color is that the .placeholder class is being added/removed on focus or blur, not when the user types. You need an additional event handler for keyup that removes the .placeholder class (this also includes my snippet from above):
var isInputSupported = 'placeholder' in document.createElement('input');
var isTextareaSupported = 'placeholder' in document.createElement('textarea');
if (!isInputSupported || !isTextareaSupported) {
$('[placeholder]').each(function(){
var $this = $(this);
if($this.val() == ''){
$this.val($this.data('placeholder')).addClass('placeholder');
}
});
$('[placeholder]').focus(function () {
var input = $(this);
if (input.val() == input.attr('placeholder') && input.data('placeholder')) {
input.val('');
input.removeClass('placeholder');
}
}).on('keyup', function(){
$(this).removeClass('placeholder')
}).blur(function () {
var input = $(this);
if (input.val() == '') {
input.addClass('placeholder');
input.val(input.attr('placeholder'));
input.data('placeholder', true);
} else {
input.data('placeholder', false);
}
}).blur().parents('form').submit(function () {
$(this).find('[placeholder]').each(function () {
var input = $(this);
if (input.val() == input.attr('placeholder') && input.data('placeholder')) {
input.val('');
}
})
});
}