I have a youtube input for the embedding code and I wish to be able to also have the user not necessarily have to input a youtube embed. But I'm stuck about how to alter my regex to accept an empty field... I have set errors if the user fails the regex and no errors if the user passes the regex, So I would imagine there would be a simple fix to the regex to accept an empty input value.
Can anybody see how I would achieve this from my code below...
Thank you for any advice.
function checkyoutube() {
var youtube = $("#youtubevalue").val();
//var youtubeReg =/^[a-zA-Z][a-zA-Z0-9-+&%#=?<>()£~_\.*#$!, \r\n]{0,300}$/;
var youtubeReg =/^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((.|-){11})(?:\S+)?$/;
if(!youtubeReg.test(youtube)) { localStorage.setItem('error', 'true');
$("#youtubefooter").text("Example https://youtu.be/12KxXnFbwbU"), $( "#youtubevalue" ).addClass( "errorclass" ), $( "#youtubevalue" ).removeClass( "noerrorclass");
}
if(youtubeReg.test(youtube)) { localStorage.setItem('error', 'false');
$("#youtubefooter").text("URL Is Good, Thanks!"), $( "#youtubevalue" ).addClass( "noerrorclass" ), $( "#youtubevalue" ).removeClass( "errorclass");
}
var youtubeB = document.getElementById('youtubevalue');
(var regex= LOTS / OF / BAD / WORDS;)'EDITED FOR STACK'
youtubeB.value=youtubeB.value.replace(regex, "****");
};
You could make the regex optional ? by using a non capturing group (?:.....)?
^(?:(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((.|-){11})(?:\S+)?)?$
var youtubeReg = /^(?:(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((.|-){11})(?:\S+)?)?$/;
var strings = [
'https://youtu.be/12KxXnFbwbU',
'',
'https://youtu'
];
strings.forEach((s) => {
console.log(s + ' ==> ' + youtubeReg.test(s));
});
Must it be done with regex? If not, you could simply trim the input and check if its empty, if empty then its good and if not apply regex.
See the below code
function checkyoutube() {
var youtubeReg =/^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((.|-){11})(?:\S+)?$/;
var youtube = $("#youtubevalue").val();
//checking for length here after trimming
if(youtube.trim().length==0||youtubeReg.test(youtube)) { localStorage.setItem('error', 'false');
$("#youtubefooter").text("URL Is Good, Thanks!"), $( "#youtubevalue" ).addClass( "noerrorclass" ), $( "#youtubevalue" ).removeClass( "errorclass");
}
else{//skipped testing for regex again here
localStorage.setItem('error', 'true');
$("#youtubefooter").text("Example https://youtu.be/12KxXnFbwbU"), $( "#youtubevalue" ).addClass( "errorclass" ), $( "#youtubevalue" ).removeClass( "noerrorclass");
}
var youtubeB = document.getElementById('youtubevalue');
(var regex= LOTS / OF / BAD / WORDS;)'EDITED FOR STACK'
youtubeB.value=youtubeB.value.replace(regex, "****");
};
Related
I'm trying to show or hide a div based on variation price of selected items.
For example, we have a product whose base (cheapest) option price is £359.
The same product also has a £455 option.
We also have a finance plugin whose minimum spend cap is £400, and the finance calculator (user front end) exists within a spoiler below our add to cart button called '.finance'.
I'd like to be able to hide this spoiler (namely it's containing div '.finance') dynamically, in response to the selected variation price, so that finance options are not visible to customers when the spend is below the aforementioned finance cap.
I've tried the following to no avail - as you can see, I'm not too handy with js:
jQuery( function( $ ) {
$( ".in_stock" ).on( "woocommerce_variation_select_change", function() {
setTimeout( function() {
if ( $( 'span.amount' >= '400' ).length ) {
$( 'div.finance' ).show( 'fast' );
} else {
$( 'div.finance' ).hide( 'fast' );
}
}, 50 );
});
});
How can I achieve that?
Make use of the snippet below on change of the amount;
jQuery( function( $ ) {
// Run on selected variation price change.
let currency_symbol = '£';
for ( let i = 0; i < $( 'p.price' ).length; i++ ) {
// Define the subtotal block.
let sub_total = $( 'p.price:contains(Subtotal ' + currency_symbol + ')' );
// Define the condition for the finance block.
let amount = Number( sub_total.text().split( ' ' + currency_symbol )[1] ) >= 400;
// Show or hide the finance block based on the condition above.
amount ? $( 'div.finance' ).show( 'fast' ) : $( 'div.finance' ).hide( 'fast' );
}
});
I'd probably lose the setTimeout because 50 milliseconds isn't go to make a lot of difference.
Assuming that span.amount is one element you want to grab its text content, coerce it to a number, and then check if it's within range.
$('.in_stock').on('woocommerce_variation_select_change', function() {
const value = Number($('span.amount').text());
if (value >= 400) {
$('div.finance').show('fast');
} else {
$('div.finance').hide('fast');
}
});
Sorry this is driving me nuts but my modal dialog box is not showing up when I switch button to a link. Basically for this functionality (sorry I had to take company sensitive data out so some of the code is missing but still works) I just want the editors to put in a link with an id or class and that link doesn't work but the address opens a dialog box with the address url in it.
I have this working with a button but this does not work with a link and code below. Also they are manually entering link into p-tag and wondering if it can be captured via href.
$(function() {
var dialog, form,
tips = $( ".validateTips" );
function addUser() {
var valid = true;
allFields.removeClass( "ui-state-error" );
valid = valid && checkLength( name, "username", 3, 16 );
valid = valid && checkLength( email, "email", 6, 80 );
valid = valid && checkLength( password, "password", 5, 16 );
valid = valid && checkRegexp( name, /^[a-z]([0-9a-z_\s])+$/i, "Username may consist of a-z, 0-9, underscores, spaces and must begin with a letter." );
valid = valid && checkRegexp( email, emailRegex, "eg. ui#jquery.com" );
valid = valid && checkRegexp( password, /^([0-9a-zA-Z])+$/, "Password field only allow : a-z 0-9" );
if ( valid ) {
$( "#users tbody" ).append( "<tr>" +
"<td>" + name.val() + "</td>" +
"<td>" + email.val() + "</td>" +
"<td>" + password.val() + "</td>" +
"</tr>" );
dialog.dialog( "close" );
}
return valid;
}
dialog = $( "#dialog-form" ).dialog({
autoOpen: false,
height: 300,
width: 350,
modal: true,
});
form = dialog.find( "form" ).on( "submit", function( event ) {
event.preventDefault();
addUser();
});
$( "#create-link" ).a().on( "click", function(e) {
e.preventDefault();
dialog.dialog( "open" );
});
});
<div>Perma-link</div>
<div id="dialog-form" title="Link Address">
<p class="validateTips">https://xyz</p>
</div>
Note - I completely understand that it is odd to capture a link in a modal box but we must do this because the vendor does not display the full active link in the url. So when our users try to share the page they copy the url in browser which takes other users no where. The link here takes them to the permanent page. I know this is stupid but needed.
When you look up an element with a jQuery selector, it returns a jQuery object that you can call jQuery defined methods on.
In your code, you have:
$( "#create-link" ).a().on( "click", function(e) {
e.preventDefault();
dialog.dialog( "open" );
});
The object returned by $("#create-link") is a jQuery object of the a tag in your html. You can only call jQuery methods on that object. The method a() is not defined as far as I know in jQuery or jQuery UI. Remove that.
As for the link itself, it doesn't make sense to add a link and then block the action of clicking the link. I'm guessing you aren't understanding the requirements, based on this comment:
the UI guys wanted me to hand it over as a link. So the last part of
this was moving the button to a link and then making the href
automatically populate the validateTips section
That reads to me like they want you to provide the user with a link.
I don't think your click event is firing when you click the link. Why not say
$( "#create-link" ).on( "click", function(e) {
e.preventDefault();
dialog.dialog( "open" );
});
Simply removing the a(). should fix things.
See here http://jsfiddle.net/eos4c25w/1/
I have the following code which loads jQuery into the page dynamically after page load and then attempts to run some jQuery of its own afterwards. The first console log of the page title works. The issue comes when it cant find the class "special-div" later on in the page and replace it with the appropriate text. Any thoughts?
//Load jQuery library using plain JavaScript
(function(){
var newscript = document.createElement('script');
newscript.type = 'text/javascript';
newscript.src = 'https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js';
document.getElementsByTagName('head')[0].appendChild(newscript);
// Poll for jQuery to come into existance
var checkReady = function(callback) {
if (window.jQuery) {
callback(jQuery);
}
else {
window.setTimeout(function() { checkReady(callback); }, 100);
}
};
// Start polling...
checkReady(function($) {
console.log( 'jQuery is loaded on: ' + $('title').text() );
$( '.special-div' ).each(function( index ) {
console.log( index + ": " + $( this ).text() );
$( this ).replaceWith( "Say something here " + $( this ).attr( "id" ) + ' ' + $( this ).attr( "title" ) );
});
});
})();
The HTML looks like this:
<div id="something" class="special-div" title="else"> </div>
The wacky CMS that I am working on only allows for me to paste in one external javascript file so i have to load in jQuery and all other scripts i need through that one file.
Edit:
so i ran a few additional tests and tried this:
console.log( 'jQuery is loaded on: ' + $( '.special-div' ).attr( "id" ) );
the response i am getting is:
jQuery is loaded on: undefined
If you want to return content of div in second console.log, use $( this ).html() instead of $( this ).text()
If you want to replace text for each $( '.special-div' ) with the content of their attributes, you have to do:
$( this ).replaceWith( "Say something here " + $( this ).attr( "id" ) + ' ' + $( this ).attr( "title" ) );
instead of
$( '.special-div' ).replaceWith( "Say something here " + $( this ).attr( "id" ) + ' ' + $( this ).attr( "title" ) );
otherwise you get the same replacement for all occurrences.
I tried it and it works.
But if you are putting it in <head> and another jQuery is loaded before it, DOM searching will run before the DOM getting ready so that it can not find the DOM.
(case of no window.setTimeout(function() { checkReady(callback); }, 100);)
(another CMS plugin might load jQuery)
So it could be better to run the script on kind of window.onload timings.
Or putting it on the end of <body> may also work.
I'm using the 'nested-list' plugin for jQuery Mobile, this one:
The problem is that when you use more than one level the plugins fails going back. For example, in the fiddle I have created I can go to 'Test 1.2.1' without problem, If I going back 1 level it works fine and I go to 'Test 1.2', but then if I tried to go up one level more (it was 'Test1') it goes up 2 levels (to 'Test').
I have checked the plugin code but I can't find the problem and I have left a message in the Git forum with no answer. Maybe someone could help me here.
Thanks in advance!
Fiddle
Looking at the plugin code, it is only designed for one level deep nesting. This is because the developer chose to remove created subpages each time you click on a parent LI. So when you get to the second level of depth, its parent has been removed from the DOM and you have to click the back button twice to get to the original page.
I have made some changes to the plugin code that should solve this problem:
In _attachBindings, I have commented out the line that removes previously created subpages:
_attachBindings: function() {
this._on({
"click": "_handleSubpageClick"
});
this._on( "body", {
"pagechange": function(){
if ( this.opening === true ) {
this.open = true;
this.opening = false;
} else if ( this.open === true ) {
//Don't remove the old LI
//this.newPage.remove();
this.open = false;
}
}
});
},...
Then in _handleSubpageClick, I check if the subpage already exists in the DOM (via data attribute added when creating the page). If not, we go through the existing code that creates the subpage, and then in the end I store the created subpage id in a data attribute on the parent LI. If it does exist we just navigate to that page.
_handleSubpageClick: function( event ) {
if( $(event.target).closest( "li" ).children( "ul" ).length == 0 ) {
return;
}
this.opening = true;
//see if we already created the subpage
var $li = $(event.target).closest( "li" );
var pid = $li.data("nextpageid");
if (pid && pid.length > 0){
this.pageID = pid;
} else {
this.newPage = $( this.options.page ).uniqueId();
this.nestedList = $( event.target ).children( "ul" )
.clone().attr( "data-" + $.mobile.ns + "role", "listview" )
.css( "display", "block" );
this.pageName = (
$( event.target.childNodes[0] ).text().replace(/^\s+|\s+$/g, '').length > 0 )?
$( event.target.childNodes[0] ).text() : $( event.target.childNodes[1] ).text();
this.pageID = this.newPage.attr( "id" );
// Build new page
this.newPage.append(
$( this.options.header ).find( "h1" ).text( this.pageName ).end()
).append(
$( this.options.content )
).find( "div.ui-content" ).append( this.nestedList );
$( "body" ).append( this.newPage );
//save subpage id as data attribute of the LI
$li.data("nextpageid", this.pageID);
}
$( "body" ).pagecontainer( "change", "#" + this.pageID );
}...
Here is your updated FIDDLE
I removed the external link to the plugin and instead copied all the code into the javascript pane and made the edits. You should be able to copy that code directly and use as the updated plugin. (Of course I did this quickly and have not rigorously tested it, so make sure it works for you).
Apologies if this is an overly simple question, but my searches are getting me nowhere.
I have a jQuery function which produces an error on some of my pages which do not contain the #message input:
Error: jQuery("#message").val() is undefined
Line: 56
And my jQuery function:
function updateCountdown()
{
var $left = 255 - jQuery( '#message' ).val().length;
jQuery( '#countdown' ).text( $left + ' Characters Remaining' );
}
$( document ).ready( function()
{
updateCountdown();
$( '#message' ).change( updateCountdown );
$( '#message' ).keyup( updateCountdown );
});
So my question is, how do I use a conditional to remove the error message from pages without the #message input? I believe my problem is a basic lack of knowledge of how JavaScript works.
I wouldn't bother to perform an explicit test on the jQuery object returned from the selector — let jQuery do that for you!
$(function() {
$('#message').each(function() {
var $self = $(this);
$self.bind('change keyup', function updateCountdown() {
$('#countdown').text((255 - $self.val().length)) + ' characters remaining');
});
});
});
If '#message' doesn't match anything, then the .each( ... ) call won't do anything.
The only problem is with your init code.. after that it'll run fine. So do:
$( document ).ready( function()
{
$( '#message' ).change( updateCountdown ).keyup( updateCountdown ).keyup();
});
Note the use of chaining.
Improve your selector to ensure that it's actually getting an input element (so that there is a value). Then check to see if your selector actually matched anything before working with it. Note that the length of the jQuery object returned is the number of matching elements (it must be greater than 0). Oh, and you can consistently use the $ function as long as there aren't any conflicts with other javascript frameworks.
function updateCountdown()
{
var msg = $('input#message');
if (msg.length > 0) {
var $left = 255 - msg.val().length;
$( '#countdown' ).text( $left + ' Characters Remaining' );
}
}
You just need to check if the jQuery object contains any items. I would do it like this.
$( document ).ready( function()
{
var $message = jQuery( '#message' );
if($message.length > 0) {
updateCountdown();
$( '#message' ).change( updateCountdown );
$( '#message' ).keyup( updateCountdown );
}
});
Then I'd change your updateCountdown() function to use the this keyword rather than doing another jQuery lookup. jQuery sets this to be the DOM element the event occurred on.
function updateCountdown()
{
var $left = 255 - jQuery( this ).val().length;
jQuery( '#countdown' ).text( $left + ' Characters Remaining' );
}