Append problems in jQuery - javascript

I have a problem in jQuery, it is that I have an array to append to an object (id) This function also after intends such as.
When I now use a "each" function in jQuery do I do it this way.
$.each(childrenObj, function(index, value)
{
$( document.createElement('ol') )
.append(
$( document.createElement('li') )
.attr('id', 'list_'+ listItem )
.append(
$( document.createElement('div') )
.addClass('listContentItem')
.html( value.contentTitle )
)
)
.appendTo('#list_'+ ( listItem - 1 ) );
listItem++;
});
As you would imagine, it will make a <ol><li>test</li></ol> where after doing the same thing over and over again depending on how many people run through.
That I would like is that I would like it to make a <ol> in an object after which I in my each loop adds <li> to it and eventually make a appendTo ('# id') after my desire but could not quite get it resolved and it causes some problems pure design front.
Hope there are some who sits with a solution and can help me a little on the road.

Create the ol outside your loop (below code is untested, but should hopefully work)
var ol = $( document.createElement('ol') );
$.each(childrenObj, function(index, value)
{
ol.append(
$( document.createElement('li') )
.append(
$( document.createElement('div') )
.addClass('listContentItem')
.html( value.contentTitle )
)
);
});
ol.appendTo('#some_id');

Related

Retrieving jQuery data from dynamic HTML element returns undefined

I am trying to retrieve data from a variable HTML element. On click, the id of the <span> element is retrieved, which I want to enable me to dynamically $([dynamic id]) select that element and request the data stored in the data attribute.
My jQuery looks like this:
$( document ).ready( function() {
$( ".checkmark" ).on( "click", ( event ) => {
let checkBoxId = "#" + event.target.id, // #checkBox1
checkBoxData = event.target.id + "-value", // checkBox1-value
checkBoxValue = $( checkBoxId ).data( checkBoxData ); // undefined
} );
} );
The HTML element targeted looks like this:
<span class="checkmark" id="checkBox1" data-checkBox1-value=-155></span>
The value of let checkBoxValue is undefined and I cannot figure out why.
Help would be greatly appreciated.
You can get attribute value of span using attr() function in jQuery
checkBoxValue = $(checkBoxId).attr(checkBoxData);
The checkBoxId variable is unnecessary because you can use the this keyword since it is the current element you are working with.
$(function() {
$(".checkmark").on("click", (event) => {
let checkBoxData = event.target.id + "-value";
let checkBoxValue = $(this).data(checkBoxData);
});
});
It seems you are having scope issues with the new ()=>{} syntax.
So, you will need to bind this to the function event handler using {self:this}. If you don't want to do this, you can use the old function(){} syntax instead.
$( document ).ready( function() {
$( ".checkmark" ).on( "click", {self:this}, ( event ) => {
var checkBoxValue = $(this).data("checkbox1-value")
alert(checkBoxValue);
} );
} );
And also as #Erwin mentioned, use only lowercase in your data- attribute name:
<span class="checkmark" id="checkbox1" data-checkbox1-value="-155"></span>
JsFiddle
It's returning undefined because it is declared incorrectly. The part after data- should be in lower case. In your case, it must be
<span class="checkmark" id="checkbox1" data-checkbox1-value=-155></span>
for the .data() to work.
this code works for me try it ;)
$( document ).ready( function() {
$( ".checkmark" ).on( "click", function() {
var checkBoxId = "#" + $(this).attr('id');
var checkBoxData = $(this).attr('id') + "-value";
$( this ).attr('data-'+ checkBoxData, 155 );
} );
});
jsfiddle link

WooCommerce event not triggering when using Select2 instead of actual select

I've built a custom website using Wordpress and WooCommerce and have installed Select2 to generate custom selects which is working fine. The issue I am having is with some of the selects on the WooCommerce pages, specifically those that trigger an event on change.
The custom selects successfully change the option selected, but the issue arises with selects that are meant to trigger an event. For example, the colour variation dropdown on the product page or the 'Sort By' select on the store page.
I've looked through the WooCommerce JS files and discovered some WooCommerce specific events that are triggered when a selection is made using the actual select box but I'm not sure how to implement this when using Select2 instead.
Here is a copy of the WooCommerce JS in relation to the event I'm talking about (in this case the change to the select for product variations):
.on( 'change', '.variations select', function() {
$form.find( 'input[name="variation_id"], input.variation_id' ).val( '' ).change();
$form.find( '.wc-no-matching-variations' ).remove();
if ( $use_ajax ) {
if ( $xhr ) {
$xhr.abort();
}
var all_attributes_chosen = true;
var some_attributes_chosen = false;
var data = {};
$form.find( '.variations select' ).each( function() {
var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
if ( $( this ).val().length === 0 ) {
all_attributes_chosen = false;
} else {
some_attributes_chosen = true;
}
data[ attribute_name ] = $( this ).val();
});
if ( all_attributes_chosen ) {
// Get a matchihng variation via ajax
data.product_id = $product_id;
$xhr = $.ajax( {
url: wc_cart_fragments_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_variation' ),
type: 'POST',
data: data,
success: function( variation ) {
if ( variation ) {
$form.find( 'input[name="variation_id"], input.variation_id' )
.val( variation.variation_id )
.change();
$form.trigger( 'found_variation', [ variation ] );
} else {
$form.trigger( 'reset_data' );
$form.find( '.single_variation_wrap' ).after( '<p class="wc-no-matching-variations woocommerce-info">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
}
}
} );
} else {
$form.trigger( 'reset_data' );
}
if ( some_attributes_chosen ) {
if ( $reset_variations.css( 'visibility' ) === 'hidden' ) {
$reset_variations.css( 'visibility', 'visible' ).hide().fadeIn();
}
} else {
$reset_variations.css( 'visibility', 'hidden' );
}
} else {
$form.trigger( 'woocommerce_variation_select_change' );
$form.trigger( 'check_variations', [ '', false ] );
$( this ).blur();
}
// Custom event for when variation selection has been changed
$form.trigger( 'woocommerce_variation_has_changed' );
} )
And then my own attempt to utilise this event:
$('#pa_colour').select2();
$('#pa_colour').on('change', function(){
var $form = $(this).parents('form');
$form.trigger( 'woocommerce_variation_select_change' );
$form.trigger( 'woocommerce_variation_has_changed' );
});
Unfortunately the site isn't live yet so I can't provide a link but hopefully you get the idea.
If someone can help me here I'd be so appreciative, I'm not exactly sure how Wordpress hooks (if this is what this is) work and I may be just missing something obvious.
Thanks,
Kathryn
This isn't a solution exactly, but I ended up replacing the Select2 plugin with the Selectric plugin and that works perfectly. Oh well! Thanks guys. http://lcdsantos.github.io/jQuery-Selectric/
I came across the same issue and found a solution in the last comment in this thread Select2 not showing selected value
The comment by Matt inspired by Kevin suggested wrapping the select2 call in $(window).bind("load", function() {...}); which worked for me.
Kudos to those guys.

jQuery get and parsing html unexpected behaviour with parent div

$.get( load_this, function( page ) {
$article = $( page ).find( ".js-Article--current" );
console.log( $(page) );
$article.removeClass( "js-Article--current" ).addClass( "Article--contentHidden" )
.children( ".js-ArticleHeader" ) .addClass( "ArticleHeader--teaser" )
.find( ".next-teaserFade" ) .addClass( "ArticleHeader-teaserFade" )
.end()
.find( ".next-teaserSqueeze" ) .addClass( "ArticleHeader-teaserSqueeze" );
$( ".js-Article--current" ).after( $article );
});
get returns whole page.
Now problem I've encountered is this:
if js-Article--current is not top level element find finds it.
if js-Article--current is top level element find cannot find it.
Why?
p.s. I know solution: filter instead of find. But why is find behaving like this? I don't get it.
find() will try to find a child element of the selector. So, if .js-Article--current is the selector, it will not find it.
filter(), instead, filters through the selectors
Check the console:
var findTest = $('div').find('#test').length;
var filterTest = $('div').filter('#test').length;
console.log('find test: ' + findTest);
console.log('filter test: ' + filterTest);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="test"></div>
<div id="anotherTest"></div>

How to add links to tabbing order when they're made visible with CSS?

Links that are subject to display: none aren't in the default tabbing order. However, when they're revealed - e.g. CSS for a drop-down menu reveals a sub-menu when a parent link gains focus - they still aren't in the tabbing order. Presumably JavaScript is required, but simply setting tabindex="0" does nothing.
The problem here is that as soon as you tab off the "Top level page with child" link, the CSS is updated and the parent of the anchor becomes display:none before the anchor can receive focus. You will need to use JavaScript to solve this problem and delay the change in the CSS using a timeout until you can determine whether the loss of focus has resulted in the focus shifting to the child element.
Setting tabindex="0" when the parent is display:none will not help, display:none means that the content might as well not be in the document.
I've come up with a solution that basically works: http://codepen.io/gyrus/pen/waKjKv/ There seem to be some issues in IE, I'm working on that. But the general idea is:
Add a small delay before hiding the drop-down
Set a data attribute to flag whether any links inside the drop-down have focus, and check this before hiding
This is just the jQuery, check the pen for more:
jQuery( document ).ready( function( $ ) {
$( '.nav' ).on( 'mouseenter focusin', '.menu-level-0.menu-item-has-children', function( e ) {
var el = $( this );
// Show sub-menu
el.attr( 'aria-expanded', 'true' )
.find( '.sub-menu-wrapper' ).show();
}).on( 'mouseleave focusout', '.menu-level-0.menu-item-has-children', function( e ) {
var el = $( this );
// Only hide sub-menu after a short delay, so links get a chance to catch focus from tabbing
setTimeout( function() {
var smw = el.find( '.sub-menu-wrapper' );
if ( smw.attr( 'data-has-focus' ) !== 'true' ) {
el.attr( 'aria-expanded', 'false' );
smw.hide();
}
}, 100 );
}).on( 'focusin', '.sub-menu-wrapper', function( e ) {
var el = $( this );
el.attr( 'data-has-focus', 'true' );
}).on( 'focusout', '.sub-menu-wrapper', function( e ) {
var el = $( this );
el.attr( 'data-has-focus', 'false' );
// Hide sub-menu on the way out
el.hide().parents( '.menu-level-0' ).attr( 'aria-expanded', 'false' );
});
});

jQuery mobile nested-list plugin bug going back

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).

Categories

Resources