I've google for this but I could no find a solution for my issue. I have some events on a js function (Immediate function invocation). Therefore the click event is not working well. It fires only on the second invocation.
The first three fields (To, Cc, and Cco) should expand when you type a long text. The click event should collapse the "To", "Cc" and "Cco" fields when you click on "Subject" field. It works, but only on the second time I click in subject.
Heres my js (IIF)
function initTextareaEvents(){
$('section textarea').on({
focusin:function( ev ) {
if($( this ).closest( '.info-box' ).length > 0){
$( this ).elastic();
}
},
keypress:function( ev ) {
var key = ev.which;
if(key == 13 || key == 32){
ev.preventDefault();
var str = $( this ).val().trim();
str += ', ';
$( this ).val( str );
}
},
click:function ( ev ) {
if($( this ).closest( '.info-box' ).length === 0){
$( '#to, #cc, #cco' ).css( 'height', 'auto' );
}
}
});
}
Here is Codepen
The first click is acting as "Focus Out" I think. try adding something like
focusout:function( ev ) {
if($( this ).closest( '.info-box' ).length > 0){
$( this ).elastic();
}
},
This seems to get you closer to the behavior you want.
Related
On the product category page, when someone clicks "Add to cart", woocommerce adds "View cart" below this button through Ajax. I found that the script which handle this is /assets/js/frontend/add-to-cart.js
Now, I want to add also "Procceed to checkout", so someone can go to checkout immediately.
This is the output of the script:
jQuery( function( $ ) {
// wc_add_to_cart_params is required to continue, ensure the object exists
if ( typeof wc_add_to_cart_params === 'undefined' )
return false;
// Ajax add to cart
$( document ).on( 'click', '.add_to_cart_button', function(e) {
// AJAX add to cart request
var $thisbutton = $( this );
if ( $thisbutton.is( '.product_type_simple' ) ) {
if ( ! $thisbutton.attr( 'data-product_id' ) )
return true;
$thisbutton.removeClass( 'added' );
$thisbutton.addClass( 'loading' );
var data = {
action: 'woocommerce_add_to_cart',
};
$.each( $thisbutton.data(), function( key, value ) {
data[key] = value;
});
// Trigger event
$( 'body' ).trigger( 'adding_to_cart', [ $thisbutton, data ] );
// Ajax action
$.post( wc_add_to_cart_params.ajax_url, data, function( response ) {
if ( ! response )
return;
var this_page = window.location.toString();
this_page = this_page.replace( 'add-to-cart', 'added-to-cart' );
if ( response.error && response.product_url ) {
window.location = response.product_url;
return;
}
// Redirect to cart option
if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {
window.location = wc_add_to_cart_params.cart_url;
return;
} else {
$thisbutton.removeClass( 'loading' );
fragments = response.fragments;
cart_hash = response.cart_hash;
// Block fragments class
if ( fragments ) {
$.each( fragments, function( key, value ) {
$( key ).addClass( 'updating' );
});
}
// Block widgets and fragments
$( '.shop_table.cart, .updating, .cart_totals' ).fadeTo( '400', '0.6' ).block({
message: null,
overlayCSS: {
opacity: 0.6
}
});
// Changes button classes
$thisbutton.addClass( 'added' );
// View cart text
if ( ! wc_add_to_cart_params.is_cart && $thisbutton.parent().find( '.added_to_cart' ).size() === 0 ) {
$thisbutton.after( ' <a href="' + wc_add_to_cart_params.cart_url + '" class="added_to_cart wc-forward" title="' +
wc_add_to_cart_params.i18n_view_cart + '">' + wc_add_to_cart_params.i18n_view_cart + '</a>' );
}
// Replace fragments
if ( fragments ) {
$.each( fragments, function( key, value ) {
$( key ).replaceWith( value );
});
}
// Unblock
$( '.widget_shopping_cart, .updating' ).stop( true ).css( 'opacity', '1' ).unblock();
// Cart page elements
$( '.shop_table.cart' ).load( this_page + ' .shop_table.cart:eq(0) > *', function() {
$( '.shop_table.cart' ).stop( true ).css( 'opacity', '1' ).unblock();
$( 'body' ).trigger( 'cart_page_refreshed' );
});
$( '.cart_totals' ).load( this_page + ' .cart_totals:eq(0) > *', function() {
$( '.cart_totals' ).stop( true ).css( 'opacity', '1' ).unblock();
});
// Trigger event so themes can refresh other areas
$( 'body' ).trigger( 'added_to_cart', [ fragments, cart_hash, $thisbutton ] );
}
});
return false;
}
return true;
});
Is there anybody who has done something similar?
If you look here from the Woocommerce repo, you can see that add-to-cart.js is localized from that class.
Unfortunately, there isn't a filter to just add your own link. What you could try is copying add-to-cart.js to your theme and set the new src of the registered add-to-cart.js to your new local copy, by using this method.
From there you can alter the this conditional found in Woocommerce repo.
So, technically yes, you could could this, but there are caveats:
You would need to repeat this process for variation products
If translation is a concern, you need to address that as well
Any time the plugin updates, you now have to comb through these files for any differences that could break functionality or cause a security issue.
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).
My question concerns the swipe event on a mobile device (I'm using a Nexus 7) with Chrome. I am working off the Jquery Mobile 1.4.2 demo which can be found here:
http://demos.jquerymobile.com/1.4.2/swipe-page/
I'll ask my question and copy the sample javascript below. I can get everything to work, both on my laptop (using Chrome) and on my tablet (using Firefox), but the swipe works maybe one out of ten times in Chrome with my tablet. Any advice? Thanks!
// Pagecreate will fire for each of the pages in this demo
// but we only need to bind once so we use "one()"
$( document ).one( "pagecreate", ".demo-page", function() {
// Initialize the external persistent header and footer
$( "#header" ).toolbar({ theme: "b" });
$( "#footer" ).toolbar({ theme: "b" });
// Handler for navigating to the next page
function navnext( next ) {
$( ":mobile-pagecontainer" ).pagecontainer( "change", next + ".html", {
transition: "slide"
});
}
// Handler for navigating to the previous page
function navprev( prev ) {
$( ":mobile-pagecontainer" ).pagecontainer( "change", prev + ".html", {
transition: "slide",
reverse: true
});
}
// Navigate to the next page on swipeleft
$( document ).on( "swipeleft", ".ui-page", function( event ) {
// Get the filename of the next page. We stored that in the data-next
// attribute in the original markup.
var next = $( this ).jqmData( "next" );
// Check if there is a next page and
// swipes may also happen when the user highlights text, so ignore those.
// We're only interested in swipes on the page.
if ( next && ( event.target === $( this )[ 0 ] ) ) {
navnext( next );
}
});
// Navigate to the next page when the "next" button in the footer is clicked
$( document ).on( "click", ".next", function() {
var next = $( ".ui-page-active" ).jqmData( "next" );
// Check if there is a next page
if ( next ) {
navnext( next );
}
});
// The same for the navigating to the previous page
$( document ).on( "swiperight", ".ui-page", function( event ) {
var prev = $( this ).jqmData( "prev" );
if ( prev && ( event.target === $( this )[ 0 ] ) ) {
navprev( prev );
}
});
$( document ).on( "click", ".prev", function() {
var prev = $( ".ui-page-active" ).jqmData( "prev" );
if ( prev ) {
navprev( prev );
}
});
});
$( document ).on( "pageshow", ".demo-page", function() {
var thePage = $( this ),
title = thePage.jqmData( "title" ),
next = thePage.jqmData( "next" ),
prev = thePage.jqmData( "prev" );
// Point the "Trivia" button to the popup for the current page.
$( "#trivia-button" ).attr( "href", "#" + thePage.find( ".trivia" ).attr( "id" ) );
// We use the same header on each page
// so we have to update the title
$( "#header h1" ).text( title );
// Prefetch the next page
// We added data-dom-cache="true" to the page so it won't be deleted
// so there is no need to prefetch it
if ( next ) {
$( ":mobile-pagecontainer" ).pagecontainer( "load", next + ".html" );
}
// We disable the next or previous buttons in the footer
// if there is no next or previous page
// We use the same footer on each page
// so first we remove the disabled class if it is there
$( ".next.ui-state-disabled, .prev.ui-state-disabled" ).removeClass( "ui-state-disabled" );
if ( ! next ) {
$( ".next" ).addClass( "ui-state-disabled" );
}
if ( ! prev ) {
$( ".prev" ).addClass( "ui-state-disabled" );
}
});
I've done the same experiment and I've observed similar results with my tablet (Nexus 7 - Google Chrome).
You should not use heavy frameworks like jQueryMobile if you are going to create a web app or a mobile website because even if these tools make your life easier at the end the result, especially on Android devices, will be slow and sluggish.
In other words you should create your own .css and .js.
If you need to manipulate the DOM very often you should also look for alternatives to jQuery.
I suggest that you use Zepto.js.
In the end, I decided to use the jQuery touchSwipe plugin and write my own code, works fine in different browsers and across devices. Some of this may not make sense without the HTML, but essentially I determine the direction of the swipe based on the variable that is passed into the method. Then, by getting various attributes and class names, I am turning on and off the display of the various divs that have previously loaded the JSON into them from another method. The way I do that is through substrings, where the last digit of the id is a number. If anyone has any comments about how this code could be more efficient, I'd be happy to hear your thoughts. Cheers.
function swipeLiterary() {
$("#read").swipe({
swipe:function(event, direction, distance, duration, fingerCount) {
switch (direction) {
case 'left':
var thisPage = $('.display').attr('id');
var nextPageNum = parseInt(thisPage.substring(8)) + 1;
var nextPage = thisPage.substring(0,8) + nextPageNum;
if (nextPageNum > 9) {
break
}
$('#' + thisPage).removeClass('display').addClass('nodisplay');
$('#' + nextPage).removeClass('nodisplay').addClass('display');
console.log(nextPage);
break;
case 'right':
var thisPage = $('.display').attr('id');
var prevPageNum = parseInt(thisPage.substring(8)) - 1;
var prevPage = thisPage.substring(0,8) + prevPageNum;
if (prevPageNum < 0){
break;
}
$('#' + thisPage).removeClass('display').addClass('nodisplay');
$('#' + prevPage).removeClass('nodisplay').addClass('display');
console.log(prevPage);
break;
case 'up':
console.log('up');
break;
}
//$(this).text("You swiped " + direction );
//console.log(this);
}
});
}
I have the following code that tries to detect swipes left and right:
$('#my_view').bind('pageinit', function() {
$( '#my_view' ).on( "swipeleft swiperight", "#myItem", function( event ) {
var listitem = $( this ),
dir = event.type === "swipeleft" ? "left" : "right";
console.log("Detected swipe!!!! " + dir);
});
});
However this only detects the right swipe and never detects a left swipe, can anyone explain why?
I created a fiddle and it seems to work fine
DEMO
Maybe for the pageinit, use $(document).on:
$(document).on("pageinit", "#my_view", function(){
$('#my_view').on( "swipeleft swiperight", "#myItem li", function( event ){
alert(event.type);
});
});
I am trying to develop a simple drag and drop 'game'. In simple terms all you do is drag and drop various items into a area and it will say correct or wrong depending on the item dragged. This is what I have so far and its not working at all and I dont know why. My knowledge of JS and jQuery leaves a lot to be desired too.
<script>
$(function() {
$( "#draggable" ).draggable();
$( "#wrong" ).draggable();
$( "#droppable" ).droppable({
drop: function( event, ui ) {
var currentId = $(this).attr('id');
if (currentId == "draggable") {
$( this )
.addClass( "highlight" )
.find( "p" )
.html( "Correct! :)" );
} else {
$( this )
.find( "p" )
.html( "Wrong! :(" );
}
}
});
});
</script>
Now that I have it working I need more instances of the draggable images but when I add more the the new ones that have been added don't work.
http://jsfiddle.net/KcruJ/9/
var currentId = $(this).attr('id');
if (currentId == "draggable")
...
Will never result true, as $(this) represents the droppable the draggable is dropped on. ui.draggable represents the draggable[1]
Try:
var currentId = $(ui.draggable).attr('id');
if (currentId == "draggable")
...
This works: http://jsfiddle.net/T6nu3/2/
$(this).attr('id');
Will always return droppable.
You need to access the dragged element:
$(ui.draggable).attr('id');
Take a look at the jQuery UI Documentation for more information.
Code:
$(function() {
$("#draggable").draggable();
$("#wrong").draggable();
$("#droppable").droppable({
drop: function(event, ui) {
var currentId = $(ui.draggable).attr('id');
if (currentId == "draggable") {
$(this).addClass("highlight").find("p").html("Correct! :)");
} else {
$(this).find("p").html("Wrong! :(");
}
}
});
});
haha well, Alex seems to have this one on lock.
There's the answer: http://jsfiddle.net/aGqHh/1/