Re: Display Message on page load

Solved

How to fix undefined value in stock message on page load?

michaelmorgan
Shopify Partner
32 2 5

Hi! I created a custom variant dropdown using the prettydropdown jquery plugin. I added functionality to display a label "In Stock" if the variant is in stock, otherwise "Custom Made" if it is out of stock or is not tracking quantity. Also if the product is tagged "2 Weeks" it displays a 2-week message and if they are tagged "4-6 Weeks" a 4-6 week message. Here is a preview of a product page.

Now I need also to display the variant label and message somewhere else on the page. I ended up adding an HTML block to the product with this code: <div class="stock-message"></div>. The issue I am having is the stock message to display the actual value on page load instead of "undefined". I know it is embedded in a click function but I have tried numerous other ways and nothing is working. The eventlistener function is working perfectly, it's the $(function() {  that needs something changed about it, whether its placement or something else. Below is the code for the stock message. Further below it (not shown) is the rest of the code for the message and label in the dropdown. I would really appreciate some help! Thanks!

Click to expand...
setTimeout(function(){  
  $('.variant-input-wrap').find('li').click(function() {
       changetext($(this));
  })
  changetext($('.variant-input-wrap').eq(0).find('li').eq(0));
},1000)
    
function changetext(element){
  var current_option = element.attr('data-value'); 
  var variant_label = "<span class='variant-label'>";
  var variant_message = "<span class='variant-message'>";
  var close_span = "</span>";

  $(function() {  
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html(variant_label + $('.prettydropdown li.selected .variant-label').html() + close_span);    
    } else {
      $('.stock-message').html(variant_label + $('.prettydropdown li.selected .variant-label').html() + close_span + variant_message + $('.prettydropdown li.selected .variant-message').html() + close_span);
    }
  });
   
  document.addEventListener('variant:change', function(event) {    
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html(variant_label + $('.prettydropdown li.selected .variant-label').html() + close_span);    
    } else {
      $('.stock-message').html(variant_label + $('.prettydropdown li.selected .variant-label').html() + close_span + variant_message + $('.prettydropdown li.selected .variant-message').html() + close_span);
    }
  }.bind(this));

 

Accepted Solution (1)
LitExtension
Shopify Partner
4901 1004 1176

This is an accepted solution.

Hi @michaelmorgan,

Please change all code:

/*!
 * jQuery Pretty Dropdowns Plugin v4.17.0 by T. H. Doan (https://thdoan.github.io/pretty-dropdowns/)
 *
 * jQuery Pretty Dropdowns by T. H. Doan is licensed under the MIT License.
 * Read a copy of the license in the LICENSE file or at https://choosealicense.com/licenses/mit/
 */

(function($) {
  $.fn.prettyDropdown = function(oOptions) {

    // Default options
    oOptions = $.extend({
      classic: true,
      customClass: 'arrow',
      width: null,
      height: 50,
      hoverIntent: -1,
      multiDelimiter: '; ',
      multiVerbosity: 99,
      selectedMarker: '&#10003;',
      afterLoad: function(){}
    }, oOptions);

    oOptions.selectedMarker = '<span aria-hidden="true" class="checked"> ' + oOptions.selectedMarker + '</span>';
    
    // Validate options
    if (isNaN(oOptions.width) && !/^\d+%$/.test(oOptions.width)) oOptions.width = null;
    if (isNaN(oOptions.height)) oOptions.height = 50;
    else if (oOptions.height<8) oOptions.height = 8;
    if (isNaN(oOptions.hoverIntent)) oOptions.hoverIntent = 200;
    if (isNaN(oOptions.multiVerbosity)) oOptions.multiVerbosity = 99;

    // Translatable strings
    var MULTI_NONE = 'None selected',
      MULTI_PREFIX = 'Selected: ',
      MULTI_POSTFIX = ' selected';

    // Globals
    var $current,
      aKeys = [
        '0','1','2','3','4','5','6','7','8','9',,,,,,,,
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
      ],
      nCount,
      nHoverIndex,
      nLastIndex,
      nTimer,
      nTimestamp,

      // Initiate pretty drop-downs
      init = function(elSel) {
        var $select = $(elSel),
          nSize = elSel.size,
          sId = elSel.name || elSel.id || '',
          sLabelId;
        // Exit if widget has already been initiated
        if ($select.data('loaded')) return;
        // Remove 'size' attribute to it doesn't affect vertical alignment
        $select.data('size', nSize).removeAttr('size');
        // Set <select> height to reserve space for <div> container
        $select.css('display', 'none').outerHeight(oOptions.height);
        nTimestamp = performance.now()*100000000000000;
        // Test whether to add 'aria-labelledby'
        if (elSel.id) {
          // Look for <label>
          var $label = $('label[for=' + elSel.id + ']');
          if ($label.length) {
            // Add 'id' to <label> if necessary
            if ($label.attr('id') && !/^menu\d{13,}$/.test($label.attr('id'))) sLabelId = $label.attr('id');
            else $label.attr('id', (sLabelId = 'menu' + nTimestamp));
          }
        }
        nCount = 0;
        var $items = $('optgroup, option', $select),
          $selected = $items.filter(':selected'),
          bMultiple = elSel.multiple,
          // Height - 2px for borders
          sHtml = '<ul' + (elSel.disabled ? '' : ' tabindex="0"') + ' role="listbox"'
            + (elSel.title ? ' title="' + elSel.title + '" aria-label="' + elSel.title + '"' : '')
            + (sLabelId ? ' aria-labelledby="' + sLabelId + '"' : '')
            + ' aria-activedescendant="item' + nTimestamp + '-1" aria-expanded="false"'
            + ' style="max-height:' + (oOptions.height-2) + 'px;margin:'
            // NOTE: $select.css('margin') returns an empty string in Firefox, so we have to get
            // each margin individually. See https://github.com/jquery/jquery/issues/3383
            + $select.css('margin-top') + ' '
            + $select.css('margin-right') + ' '
            + $select.css('margin-bottom') + ' '
            + $select.css('margin-left') + ';">';
        if (bMultiple) {
          sHtml += renderItem(null, 'selected');
          $items.each(function() {
            if (this.selected) {
              sHtml += renderItem(this, '', true)
            } else {
              sHtml += renderItem(this);
            }
          });
        } else {
          if (oOptions.classic) {
            $items.each(function() {
              sHtml += renderItem(this);
            });
          } else {
            sHtml += renderItem($selected[0], 'selected');
            $items.filter(':not(:selected)').each(function() {
              sHtml += renderItem(this);
            });
          }
        }
        sHtml += '</ul>';
        $select.wrap('<div ' + (sId ? 'id="prettydropdown-' + sId + '" ' : '')
          + 'class="prettydropdown '
          + (oOptions.classic ? 'classic ' : '')
          + (elSel.disabled ? 'disabled ' : '')
          + (bMultiple ? 'multiple ' : '')
          + oOptions.customClass + ' loading"'
          // NOTE: For some reason, the container height is larger by 1px if the <select> has the
          // 'multiple' attribute or 'size' attribute with a value larger than 1. To fix this, we
          // have to inline the height.
          + ((bMultiple || nSize>1) ? ' style="height:' + oOptions.height + 'px;"' : '')
          +'></div>').before(sHtml).data('loaded', true);
        var $dropdown = $select.parent().children('ul'),
          nWidth = $dropdown.outerWidth(true),
          nOuterWidth;
        $items = $dropdown.children();
        // Update default selected values for multi-select menu
        if (bMultiple) updateSelected($dropdown);
        else if (oOptions.classic) $('[data-value="' + $selected.val().replace(/"/g, '″') + '"]', $dropdown).addClass('selected').append(oOptions.selectedMarker);
        // Calculate width if initially hidden
        if ($dropdown.width()<=0) {
          var $clone = $dropdown.parent().clone().css({
              position: 'absolute',
              top: '-100%'
            });
            $('body').append($clone);
            nWidth = $clone.children('ul').outerWidth(true);
            $('li', $clone).width(nWidth);
            nOuterWidth = $clone.children('ul').outerWidth(true);
            $clone.remove();
        }
        // Set dropdown width and event handler
        // NOTE: Setting width using width(), then css() because width() only can return a float,
        // which can result in a missing right border when there is a scrollbar.
        $items.width(nWidth).css('width', $items.css('width'));
        if (oOptions.width) {
          $dropdown.parent().css('min-width', $items.css('width'));
          $dropdown.css('width', '100%');
          $items.css('width', '100%');
        }
        $items.click(function() {
          var $li = $(this),
            $selected = $dropdown.children('.selected');
          // Ignore disabled menu
          if ($dropdown.parent().hasClass('disabled')) return;
          // Only update if not disabled, not a label, and a different value selected
          if ($dropdown.hasClass('active') && !$li.hasClass('disabled') && !$li.hasClass('label') && $li.data('value').toString().replace(/"/g, '″')!==$selected.data('value').toString().replace(/"/g, '″')) {
            // Select highlighted item
            if (bMultiple) {
              if ($li.children('span.checked').length) $li.children('span.checked').remove();
              else $li.append(oOptions.selectedMarker);
              // Sync <select> element
              $dropdown.children(':not(.selected)').each(function(nIndex) {
                $('optgroup, option', $select).eq(nIndex).prop('selected', $(this).children('span.checked').length>0);
              });
              // Update selected values for multi-select menu
              updateSelected($dropdown);
            } else {
              $selected.removeClass('selected').children('span.checked').remove();
              $li.addClass('selected').append(oOptions.selectedMarker);
              if (!oOptions.classic) $dropdown.prepend($li);
              $dropdown.removeClass('reverse').attr('aria-activedescendant', $li.attr('id'));
              if ($selected.data('group') && !oOptions.classic) $dropdown.children('.label').filter(function() {
                return $(this).text()===$selected.data('group');
              }).after($selected);
              // Sync <select> element
              $('optgroup, option', $select).filter(function() {
                // <option>: this.value = this.text, $li.data('value') = $li.contents()
                // <option value="">: this.value = "", $li.data('value') = undefined
                return (this.value.replace(/"/g, '″')+'|'+this.text.replace(/"/g, '″'))===($li.data('value')||'')+'|'+$li.contents().filter(function() {
                    // Filter out selected marker
                    return this.nodeType===3;
                  }).text();
              }).prop('selected', true);
            }
            $select.get(0).dispatchEvent(new Event('change'))
          }
          if ($li.hasClass('selected') || !bMultiple) {
            $dropdown.toggleClass('active');
            $dropdown.attr('aria-expanded', $dropdown.hasClass('active'));
          }
          // Try to keep drop-down menu within viewport
          if ($dropdown.hasClass('active')) {
            // Close any other open menus
            if ($('.prettydropdown > ul.active').length>1) {
              resetDropdown($('.prettydropdown > ul.active').not($dropdown));
              $('.prettydropdown > ul.active').not($dropdown).removeClass('active');
            }
            var nWinHeight = window.innerHeight,
              nMaxHeight,
              nOffsetTop = $dropdown.offset().top,
              nScrollTop = $(document).scrollTop(),
              nDropdownHeight = $dropdown.outerHeight();
            if (nSize) {
              nMaxHeight = nSize*(oOptions.height-2);
              if (nMaxHeight<nDropdownHeight-2) nDropdownHeight = nMaxHeight+2;
            }
            var nDropdownBottom = nOffsetTop-nScrollTop+nDropdownHeight;
            if (nDropdownBottom>nWinHeight) {
              // Expand to direction that has the most space
              if (nOffsetTop-nScrollTop>nWinHeight-(nOffsetTop-nScrollTop+oOptions.height)) {
                $dropdown.addClass('reverse');
                if (!oOptions.classic) $dropdown.append($selected);
                if (nOffsetTop-nScrollTop+oOptions.height<nDropdownHeight) {
                  $dropdown.outerHeight(nOffsetTop-nScrollTop+oOptions.height);
                  // Ensure the selected item is in view
                  $dropdown.scrollTop(nDropdownHeight);
                }
              } else {
                $dropdown.height($dropdown.height()-(nDropdownBottom-nWinHeight));
              }
            }
            if (nMaxHeight && nMaxHeight<$dropdown.height()) $dropdown.css('height', nMaxHeight + 'px');
            // Ensure the selected item is in view
            if (oOptions.classic) $dropdown.scrollTop($selected.index()*(oOptions.height-2));
          } else {
            $dropdown.data('clicked', true);
            resetDropdown($dropdown[0]);
          }
        });
        $dropdown.on({
          focusin: function() {
            // Unregister any existing handlers first to prevent duplicate firings
            $(window).off('keydown', handleKeypress).on('keydown', handleKeypress);
          },
          focusout: function() {
            $(window).off('keydown', handleKeypress);
          },
          mouseenter: function() {
            $dropdown.data('hover', true);
          },
          mouseleave: resetDropdown,
          mousemove:  hoverDropdownItem
        });
        if (oOptions.hoverIntent<0) {
          $(document).click(function(e) {
            if ($dropdown.data('hover') && !$dropdown[0].contains(e.target)) resetDropdown($dropdown[0]);
          });
        }
        // Put focus on menu when user clicks on label
        if (sLabelId) $('#' + sLabelId).off('click', handleFocus).click(handleFocus);
        // Done with everything!
        $dropdown.parent().width(oOptions.width||nOuterWidth||$dropdown.outerWidth(true)).removeClass('loading');
        oOptions.afterLoad();
      },

      // Manage widget focusing
      handleFocus = function(e) {
        $('ul[aria-labelledby=' + e.target.id + ']').focus();
      },

      // Manage keyboard navigation
      handleKeypress = function(e) {
        var $dropdown = $('.prettydropdown > ul.active, .prettydropdown > ul:focus');
        if (!$dropdown.length) return;
        if (e.which===9) { // Tab
          resetDropdown($dropdown[0]);
          return;
        } else {
          // Intercept non-Tab keys only
          e.preventDefault();
          e.stopPropagation();
        }
        var $items = $dropdown.children(),
          bOpen = $dropdown.hasClass('active'),
          nItemsHeight = $dropdown.height()/(oOptions.height-2),
          nItemsPerPage = nItemsHeight%1<0.5 ? Math.floor(nItemsHeight) : Math.ceil(nItemsHeight),
          sKey;
        nHoverIndex = Math.max(0, $dropdown.children('.hover').index());
        nLastIndex = $items.length-1;
        $current = $items.eq(nHoverIndex);
        $dropdown.data('lastKeypress', +new Date());
        switch (e.which) {
          case 13: // Enter
            if (!bOpen) {
              $current = $items.filter('.selected');
              toggleHover($current, 1);
            }
            $current.click();
            break;
          case 27: // Esc
            if (bOpen) resetDropdown($dropdown[0]);
            break;
          case 32: // Space
            if (bOpen) {
              sKey = ' ';
            } else {
              $current = $items.filter('.selected');
              toggleHover($current, 1);
              $current.click();
            }
            break;
          case 33: // Page Up
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(Math.max(nHoverIndex-nItemsPerPage-1, 0)), 1);
            }
            break;
          case 34: // Page Down
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(Math.min(nHoverIndex+nItemsPerPage-1, nLastIndex)), 1);
            }
            break;
          case 35: // End
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(nLastIndex), 1);
            }
            break;
          case 36: // Home
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(0), 1);
            }
            break;
          case 38: // Up
            if (bOpen) {
              toggleHover($current, 0);
              // If not already key-navigated or first item is selected, cycle to the last item; or
              // else select the previous item
              toggleHover(nHoverIndex ? $items.eq(nHoverIndex-1) : $items.eq(nLastIndex), 1);
            }
            break;
          case 40: // Down
            if (bOpen) {
              toggleHover($current, 0);
              // If last item is selected, cycle to the first item; or else select the next item
              toggleHover(nHoverIndex===nLastIndex ? $items.eq(0) : $items.eq(nHoverIndex+1), 1);
            }
            break;
          default:
            if (bOpen) sKey = aKeys[e.which-48];
        }
        if (sKey) { // Alphanumeric key pressed
          clearTimeout(nTimer);
          $dropdown.data('keysPressed', $dropdown.data('keysPressed')===undefined ? sKey : $dropdown.data('keysPressed') + sKey);
          nTimer = setTimeout(function() {
            $dropdown.removeData('keysPressed');
            // NOTE: Windows keyboard repeat delay is 250-1000 ms. See
            // https://technet.microsoft.com/en-us/library/cc978658.aspx
          }, 300);
          // Build index of matches
          var aMatches = [],
            nCurrentIndex = $current.index();
          $items.each(function(nIndex) {
            if ($(this).text().toLowerCase().indexOf($dropdown.data('keysPressed'))===0) aMatches.push(nIndex);
          });
          if (aMatches.length) {
            // Cycle through items matching key(s) pressed
            for (var i=0; i<aMatches.length; ++i) {
              if (aMatches[i]>nCurrentIndex) {
                toggleHover($items, 0);
                toggleHover($items.eq(aMatches[i]), 1);
                break;
              }
              if (i===aMatches.length-1) {
                toggleHover($items, 0);
                toggleHover($items.eq(aMatches[0]), 1);
              }
            }
          }
        }
      },

      // Highlight menu item
      hoverDropdownItem = function(e) {
        var $dropdown = $(e.currentTarget);
        if (e.target.nodeName!=='LI' || !$dropdown.hasClass('active') || new Date()-$dropdown.data('lastKeypress')<200) return;
        toggleHover($dropdown.children(), 0, 1);
        toggleHover($(e.target), 1, 1);
      },

      // Construct menu item
      // elOpt is null for first item in multi-select menus
      renderItem = function(elOpt, sClass, bSelected) {
        var sGroup = '',
          sText = '',
          sTitle;
        sClass = sClass || '';
        if (elOpt) {
          switch (elOpt.nodeName) {
            case 'OPTION':
              if (elOpt.parentNode.nodeName==='OPTGROUP') sGroup = elOpt.parentNode.getAttribute('label');
              sText = (elOpt.getAttribute('data-prefix') || '') + elOpt.text + (elOpt.getAttribute('data-suffix') || '');
              break;
            case 'OPTGROUP':
              sClass += ' label';
              sText = (elOpt.getAttribute('data-prefix') || '') + elOpt.getAttribute('label') + (elOpt.getAttribute('data-suffix') || '');
              break;
          }
         // if (elOpt.disabled || (sGroup && elOpt.parentNode.disabled)) sClass += ' disabled';
          sTitle = elOpt.title;
          if (sGroup && !sTitle) sTitle = elOpt.parentNode.title;
        }
        ++nCount;
        return '<li id="item' + nTimestamp + '-' + nCount + '"'
          + (sGroup ? ' data-group="' + sGroup + '"' : '')
          + (elOpt && (elOpt.value||oOptions.classic) ? ' data-value="' + elOpt.value.replace(/"/g, '″') + '"' : '')
          + (elOpt && elOpt.nodeName==='OPTION' ? ' role="option"' : '')
          + (sTitle ? ' title="' + sTitle + '" aria-label="' + sTitle + '"' : '')
          + (sClass ? ' class="' + $.trim(sClass) + '"' : '')
          + ((oOptions.height!==50) ? ' style="height:' + (oOptions.height-2)
          + 'px;line-height:' + (oOptions.height-4) + 'px;"' : '') + '>' + sText
          + ((bSelected || sClass==='selected') ? oOptions.selectedMarker : '') + '</li>';
      },

      // Reset menu state
      // @param o Event or Element object
      resetDropdown = function(o) {
        if (oOptions.hoverIntent<0 && o.type==='mouseleave') return;
        var $dropdown = $(o.currentTarget||o);
        $dropdown.data('hover', false);
        clearTimeout(nTimer);
        nTimer = setTimeout(function() {
          if ($dropdown.data('hover')) return;
          if ($dropdown.hasClass('reverse') && !oOptions.classic) $dropdown.prepend($dropdown.children(':last-child'));
          $dropdown.removeClass('active reverse').removeData('clicked').attr('aria-expanded', 'false').css('height', '');
          $dropdown.children().removeClass('hover nohover');
          // Update focus for NVDA screen readers
          $dropdown.attr('aria-activedescendant', $dropdown.children('.selected').attr('id'));
        }, (o.type==='mouseleave' && !$dropdown.data('clicked')) ? oOptions.hoverIntent : 0);
      },

      // Set menu item hover state
      // bNoScroll set on hoverDropdownItem()
      toggleHover = function($li, bOn, bNoScroll) {
        if (bOn) {
          var $dropdown = $li.parent();
          $li.removeClass('nohover').addClass('hover');
          // Update focus for NVDA screen readers
          $dropdown.attr('aria-activedescendant', $li.attr('id'));
          if ($li.length===1 && $current && !bNoScroll) {
            // Ensure items are always in view
            var nDropdownHeight = $dropdown.outerHeight(),
              nItemOffset = $li.offset().top-$dropdown.offset().top-1; // -1px for top border
            if ($li.index()===0) {
              $dropdown.scrollTop(0);
            } else if ($li.index()===nLastIndex) {
              $dropdown.scrollTop($dropdown.children().length*oOptions.height);
            } else {
              if (nItemOffset+oOptions.height>nDropdownHeight) $dropdown.scrollTop($dropdown.scrollTop()+oOptions.height+nItemOffset-nDropdownHeight);
              else if (nItemOffset<0) $dropdown.scrollTop($dropdown.scrollTop()+nItemOffset);
            }
          }
        } else {
          $li.removeClass('hover').addClass('nohover');
        }
      },

      // Update selected values for multi-select menu
      updateSelected = function($dropdown) {
        var $select = $dropdown.parent().children('select'),
          aSelected = $('option', $select).map(function() {
            if (this.selected) return this.text;
          }).get(),
          sSelected;
        if (oOptions.multiVerbosity>=aSelected.length) sSelected = aSelected.join(oOptions.multiDelimiter) || MULTI_NONE;
        else sSelected = aSelected.length + '/' + $('option', $select).length + MULTI_POSTFIX;
        if (sSelected) {
          var sTitle = ($select.attr('title') ? $select.attr('title') : '') + (aSelected.length ? '\n' + MULTI_PREFIX + aSelected.join(oOptions.multiDelimiter) : '');
          $dropdown.children('.selected').text(sSelected);
          $dropdown.attr({
            'title': sTitle,
            'aria-label': sTitle
          });
        } else {
          $dropdown.children('.selected').empty();
          $dropdown.attr({
            'title': $select.attr('title'),
            'aria-label': $select.attr('title')
          });
        }
      };
    
setTimeout(function(){  
  $('.variant-input-wrap').find('li').click(function() {
     changetext($(this));
  })
  changetext($('.variant-input-wrap').eq(0).find('li').eq(0));

  $('.stock-message').ready(function() {
     stockMessage($(this));
  })
},1000)

function stockMessage() {
  // var variant_message = $('.variant-wrapper').last().find('.variant-message').html();
   
  // $('.hidden-variant option').first().ready(function() {    
  //   if($(this).attr('data-available')=='true') {
  //     $('.stock-message').html("<span class='variant-label'>" + "In Stock" + "</span>");    
  //   } else {
  //     $('.stock-message').html("<span class='variant-label'>" + "Custom Made" + "</span>" + "<span class='variant-message'>" + variant_message + "</span>");
  //   }
  // });
}
    
function changetext(element){
  var current_option = element.attr('data-value'); 
   
  document.addEventListener('variant:change', function(event) {    
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");    
    } else if($.trim($('.prettydropdown li.selected .variant-message').html())!='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    }
  }.bind(this));
  
  setTimeout(function(){
    $('.variant-input-wrap').last().find('li').each(function(){
      if( $('.variant-input-wrap').eq(2).length > 0){
        var first_option = $('.variant-input-wrap').eq(0).find('.selected').attr('data-value');
        var second_option = $('.variant-input-wrap').eq(1).find('.selected').attr('data-value');
        var current_elem = $(this); 
        var unavailable = false;
        $('.hidden-variant option').each(function(){
          if($(this).attr('value') == first_option + ' / ' + second_option + ' / ' + current_elem.attr('data-value') && $(this).attr('data-available') == 'true'){ 
            current_elem.html(current_elem.attr('data-value') + '<span class="variant-label">In Stock</span>');
            unavailable = true;
          }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value') + '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">' + $('.hidden-variant option').attr('data-text') + '</span>');
        }
      }
      else if( $('.variant-input-wrap').eq(1).length > 0){
        var first_option = $('.variant-input-wrap').eq(0).find('.selected').attr('data-value');
        var current_elem = $(this);
        var unavailable = false;
        $('.hidden-variant option').each(function(){
          if($(this).attr('value') == first_option +' / ' + current_elem.attr('data-value') && $(this).attr('data-available') == 'true'){
            current_elem.html(current_elem.attr('data-value') + '<span class="variant-label">In Stock</span>');
            unavailable = true;
          }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value') + '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">' + $('.hidden-variant option').attr('data-text') + '</span>');
        }
      }
      else{
        var current_elem = $(this);
        var option_value = $(this).attr('data-value');
        var unavailable = false;
        $('.hidden-variant option').each(function(){
            if($(this).attr('value') == option_value && $(this).attr('data-available') == 'true'){
              current_elem.html(option_value+ '<span class="variant-label">In Stock</span>');
              unavailable = true;
            }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value')+ '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">'+$('.hidden-variant option').attr('data-text')+'</span>');
        }
      }
    })

    // update default
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html("In Stock");    
    } else if($.trim($('.prettydropdown li.selected .variant-message').html())!='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    }
  },500)
}
    
    /**
     * Public Functions
     */

    // Resync the menu with <select> to reflect state changes
    this.refresh = function(oOptions) {
      return this.each(function() {
        var $select = $(this);
        $select.prevAll('ul').remove();
        $select.unwrap().data('loaded', false);
        this.size = $select.data('size');
        init(this);
      });
    };

    return this.each(function() {
      init(this);
    });

  };
}(jQuery));
LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com

View solution in original post

Replies 19 (19)

LitExtension
Shopify Partner
4901 1004 1176

Hi @michaelmorgan,

Please send your site and if your site is password protected, please send me the password. I will check it.

LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com
michaelmorgan
Shopify Partner
32 2 5

Here is a preview.  I have been trying to work through a solution so the code has changed since. here is the updated code. Couple things to note is that I need the message to display for products that don't have any variants, and to basically display the variant label and message HTML of the selected dropdown. The label and message will always display in the last variant wrapper if that helps

Here is the jquery code of the whole message setup:

 

function stockMessage() {
  var variant_message = $('.variant-wrapper').last().find('.variant-message').html();
   
  $('.hidden-variant option').first().ready(function() {    
    if($(this).attr('data-available')=='true') {
      $('.stock-message').html("<span class='variant-label'>" + "In Stock" + "</span>");    
    } else {
      $('.stock-message').html("<span class='variant-label'>" + "Custom Made" + "</span>" + "<span class='variant-message'>" + variant_message + "</span>");
    }
  });
}
function changetext(element){
  var current_option = element.attr('data-value'); 
   
  document.addEventListener('variant:change', function(event) {    
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");    
    } else if($.trim($('.prettydropdown li.selected .variant-message').html())!='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    }
  }.bind(this));
  
  setTimeout(function(){
    $('.variant-input-wrap').last().find('li').each(function(){
      if( $('.variant-input-wrap').eq(2).length > 0){
        var first_option = $('.variant-input-wrap').eq(0).find('.selected').attr('data-value');
        var second_option = $('.variant-input-wrap').eq(1).find('.selected').attr('data-value');
        var current_elem = $(this); 
        var unavailable = false;
        $('.hidden-variant option').each(function(){
          if($(this).attr('value') == first_option + ' / ' + second_option + ' / ' + current_elem.attr('data-value') && $(this).attr('data-available') == 'true'){ 
            current_elem.html(current_elem.attr('data-value') + '<span class="variant-label">In Stock</span>');
            unavailable = true;
          }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value') + '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">' + $('.hidden-variant option').attr('data-text') + '</span>');
        }
      }
      else if( $('.variant-input-wrap').eq(1).length > 0){
        var first_option = $('.variant-input-wrap').eq(0).find('.selected').attr('data-value');
        var current_elem = $(this);
        var unavailable = false;
        $('.hidden-variant option').each(function(){
          if($(this).attr('value') == first_option +' / ' + current_elem.attr('data-value') && $(this).attr('data-available') == 'true'){
            current_elem.html(current_elem.attr('data-value') + '<span class="variant-label">In Stock</span>');
            unavailable = true;
          }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value') + '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">' + $('.hidden-variant option').attr('data-text') + '</span>');
        }
      }
      else{
        var current_elem = $(this);
        var option_value = $(this).attr('data-value');
        var unavailable = false;
        $('.hidden-variant option').each(function(){
            if($(this).attr('value') == option_value && $(this).attr('data-available') == 'true'){
              current_elem.html(option_value+ '<span class="variant-label">In Stock</span>');
              unavailable = true;
            }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value')+ '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">'+$('.hidden-variant option').attr('data-text')+'</span>');
        }
      }
    })
  },500)
}

 

 Here is the code of our hidden data in the product form:

 

  <select class="hidden-variant hide no-js">
    {% for variant in product.variants %}
      {%- assign option_text = '' -%}
        {% if product.tags contains '2 Weeks' %}
            {%- assign option_text = 'Estimated production time is 2 weeks' -%}
        {% elsif product.tags contains '4-6 Weeks' %}
            {%- assign option_text = 'Estimated production time is 4-6 weeks' -%}
        {% elsif variant.inventory_management == null %}
            {% assign option_text = 'Estimated production time is 2-3 weeks' %}
        {% endif %}
      <option value="{{variant.title | replace:'"', '&Prime;'}}" data-available="{% if variant.inventory_quantity <= 0 %}false{% else %}true{% endif %}" data-id="{{variant.id}}" data-title="{{variant.title | replace:' / ','' | replace:'"', '&Prime;'}}" data-text="{{option_text}}">{{variant.title | replace:'"', '&Prime;'}}</option>
    {% endfor %}
  </select>

 

Thanks!

LitExtension
Shopify Partner
4901 1004 1176

Hi @michaelmorgan,

I really don't get it, are you trying to show it for products with no variation and hide it if the product has a variant?

Is it what you want?

LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com
michaelmorgan
Shopify Partner
32 2 5

Hey, 

I need to display it for every product. So products that have variants will have the message displayed twice. Sorry, I forgot one portion of the code that is at the top.

setTimeout(function(){  
  $('.variant-input-wrap').find('li').click(function() {
       changetext($(this));
  })
  changetext($('.variant-input-wrap').eq(0).find('li').eq(0));

  $('.stock-message').ready(function() {
       stockMessage($(this));
  })
},1000)
LitExtension
Shopify Partner
4901 1004 1176

Hi @michaelmorgan,

Please send me the preview link, I will check it for you

LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com
michaelmorgan
Shopify Partner
32 2 5

Here is the link. Right now it is just displaying the first option on page load, so if someone refreshes the page after they have selected a different option with a different message, it will be wrong.

LitExtension
Shopify Partner
4901 1004 1176

Hi @michaelmorgan,

Please change code here:

Screenshot.png

function stockMessage() {
  var variant_message = $('.variant-wrapper').last().find('.variant-message').html();
   
  $('.hidden-variant option').first().ready(function() {    
    if($(this).attr('data-available')=='true') {
      $('.stock-message').html("<span class='variant-label'>" + "In Stock" + "</span>");    
    } else {
      $('.stock-message').html("<span class='variant-label'>" + "Custom Made" + "</span>" + "<span class='variant-message'>" + variant_message + "</span>");
    }
  });
}

=>

function stockMessage() {
  if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
    $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");    
  } else if($.trim($('.prettydropdown li.selected .variant-message').html())!='') {
    $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
  }
}

Hope it helps!

LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com
michaelmorgan
Shopify Partner
32 2 5

I've tried this before and it still comes up as undefined.

michaelmorgan_0-1661150983334.jpeg

 

LitExtension
Shopify Partner
4901 1004 1176

Hi @michaelmorgan,

Please change all code jquery.prettydropdowns.js file:

/*!
 * jQuery Pretty Dropdowns Plugin v4.17.0 by T. H. Doan (https://thdoan.github.io/pretty-dropdowns/)
 *
 * jQuery Pretty Dropdowns by T. H. Doan is licensed under the MIT License.
 * Read a copy of the license in the LICENSE file or at https://choosealicense.com/licenses/mit/
 */

(function($) {
  $.fn.prettyDropdown = function(oOptions) {

    // Default options
    oOptions = $.extend({
      classic: true,
      customClass: 'arrow',
      width: null,
      height: 50,
      hoverIntent: -1,
      multiDelimiter: '; ',
      multiVerbosity: 99,
      selectedMarker: '&#10003;',
      afterLoad: function(){}
    }, oOptions);

    oOptions.selectedMarker = '<span aria-hidden="true" class="checked"> ' + oOptions.selectedMarker + '</span>';
    
    // Validate options
    if (isNaN(oOptions.width) && !/^\d+%$/.test(oOptions.width)) oOptions.width = null;
    if (isNaN(oOptions.height)) oOptions.height = 50;
    else if (oOptions.height<8) oOptions.height = 8;
    if (isNaN(oOptions.hoverIntent)) oOptions.hoverIntent = 200;
    if (isNaN(oOptions.multiVerbosity)) oOptions.multiVerbosity = 99;

    // Translatable strings
    var MULTI_NONE = 'None selected',
      MULTI_PREFIX = 'Selected: ',
      MULTI_POSTFIX = ' selected';

    // Globals
    var $current,
      aKeys = [
        '0','1','2','3','4','5','6','7','8','9',,,,,,,,
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
      ],
      nCount,
      nHoverIndex,
      nLastIndex,
      nTimer,
      nTimestamp,

      // Initiate pretty drop-downs
      init = function(elSel) {
        var $select = $(elSel),
          nSize = elSel.size,
          sId = elSel.name || elSel.id || '',
          sLabelId;
        // Exit if widget has already been initiated
        if ($select.data('loaded')) return;
        // Remove 'size' attribute to it doesn't affect vertical alignment
        $select.data('size', nSize).removeAttr('size');
        // Set <select> height to reserve space for <div> container
        $select.css('display', 'none').outerHeight(oOptions.height);
        nTimestamp = performance.now()*100000000000000;
        // Test whether to add 'aria-labelledby'
        if (elSel.id) {
          // Look for <label>
          var $label = $('label[for=' + elSel.id + ']');
          if ($label.length) {
            // Add 'id' to <label> if necessary
            if ($label.attr('id') && !/^menu\d{13,}$/.test($label.attr('id'))) sLabelId = $label.attr('id');
            else $label.attr('id', (sLabelId = 'menu' + nTimestamp));
          }
        }
        nCount = 0;
        var $items = $('optgroup, option', $select),
          $selected = $items.filter(':selected'),
          bMultiple = elSel.multiple,
          // Height - 2px for borders
          sHtml = '<ul' + (elSel.disabled ? '' : ' tabindex="0"') + ' role="listbox"'
            + (elSel.title ? ' title="' + elSel.title + '" aria-label="' + elSel.title + '"' : '')
            + (sLabelId ? ' aria-labelledby="' + sLabelId + '"' : '')
            + ' aria-activedescendant="item' + nTimestamp + '-1" aria-expanded="false"'
            + ' style="max-height:' + (oOptions.height-2) + 'px;margin:'
            // NOTE: $select.css('margin') returns an empty string in Firefox, so we have to get
            // each margin individually. See https://github.com/jquery/jquery/issues/3383
            + $select.css('margin-top') + ' '
            + $select.css('margin-right') + ' '
            + $select.css('margin-bottom') + ' '
            + $select.css('margin-left') + ';">';
        if (bMultiple) {
          sHtml += renderItem(null, 'selected');
          $items.each(function() {
            if (this.selected) {
              sHtml += renderItem(this, '', true)
            } else {
              sHtml += renderItem(this);
            }
          });
        } else {
          if (oOptions.classic) {
            $items.each(function() {
              sHtml += renderItem(this);
            });
          } else {
            sHtml += renderItem($selected[0], 'selected');
            $items.filter(':not(:selected)').each(function() {
              sHtml += renderItem(this);
            });
          }
        }
        sHtml += '</ul>';
        $select.wrap('<div ' + (sId ? 'id="prettydropdown-' + sId + '" ' : '')
          + 'class="prettydropdown '
          + (oOptions.classic ? 'classic ' : '')
          + (elSel.disabled ? 'disabled ' : '')
          + (bMultiple ? 'multiple ' : '')
          + oOptions.customClass + ' loading"'
          // NOTE: For some reason, the container height is larger by 1px if the <select> has the
          // 'multiple' attribute or 'size' attribute with a value larger than 1. To fix this, we
          // have to inline the height.
          + ((bMultiple || nSize>1) ? ' style="height:' + oOptions.height + 'px;"' : '')
          +'></div>').before(sHtml).data('loaded', true);
        var $dropdown = $select.parent().children('ul'),
          nWidth = $dropdown.outerWidth(true),
          nOuterWidth;
        $items = $dropdown.children();
        // Update default selected values for multi-select menu
        if (bMultiple) updateSelected($dropdown);
        else if (oOptions.classic) $('[data-value="' + $selected.val().replace(/"/g, '″') + '"]', $dropdown).addClass('selected').append(oOptions.selectedMarker);
        // Calculate width if initially hidden
        if ($dropdown.width()<=0) {
          var $clone = $dropdown.parent().clone().css({
              position: 'absolute',
              top: '-100%'
            });
            $('body').append($clone);
            nWidth = $clone.children('ul').outerWidth(true);
            $('li', $clone).width(nWidth);
            nOuterWidth = $clone.children('ul').outerWidth(true);
            $clone.remove();
        }
        // Set dropdown width and event handler
        // NOTE: Setting width using width(), then css() because width() only can return a float,
        // which can result in a missing right border when there is a scrollbar.
        $items.width(nWidth).css('width', $items.css('width'));
        if (oOptions.width) {
          $dropdown.parent().css('min-width', $items.css('width'));
          $dropdown.css('width', '100%');
          $items.css('width', '100%');
        }
        $items.click(function() {
          var $li = $(this),
            $selected = $dropdown.children('.selected');
          // Ignore disabled menu
          if ($dropdown.parent().hasClass('disabled')) return;
          // Only update if not disabled, not a label, and a different value selected
          if ($dropdown.hasClass('active') && !$li.hasClass('disabled') && !$li.hasClass('label') && $li.data('value').toString().replace(/"/g, '″')!==$selected.data('value').toString().replace(/"/g, '″')) {
            // Select highlighted item
            if (bMultiple) {
              if ($li.children('span.checked').length) $li.children('span.checked').remove();
              else $li.append(oOptions.selectedMarker);
              // Sync <select> element
              $dropdown.children(':not(.selected)').each(function(nIndex) {
                $('optgroup, option', $select).eq(nIndex).prop('selected', $(this).children('span.checked').length>0);
              });
              // Update selected values for multi-select menu
              updateSelected($dropdown);
            } else {
              $selected.removeClass('selected').children('span.checked').remove();
              $li.addClass('selected').append(oOptions.selectedMarker);
              if (!oOptions.classic) $dropdown.prepend($li);
              $dropdown.removeClass('reverse').attr('aria-activedescendant', $li.attr('id'));
              if ($selected.data('group') && !oOptions.classic) $dropdown.children('.label').filter(function() {
                return $(this).text()===$selected.data('group');
              }).after($selected);
              // Sync <select> element
              $('optgroup, option', $select).filter(function() {
                // <option>: this.value = this.text, $li.data('value') = $li.contents()
                // <option value="">: this.value = "", $li.data('value') = undefined
                return (this.value.replace(/"/g, '″')+'|'+this.text.replace(/"/g, '″'))===($li.data('value')||'')+'|'+$li.contents().filter(function() {
                    // Filter out selected marker
                    return this.nodeType===3;
                  }).text();
              }).prop('selected', true);
            }
            $select.get(0).dispatchEvent(new Event('change'))
          }
          if ($li.hasClass('selected') || !bMultiple) {
            $dropdown.toggleClass('active');
            $dropdown.attr('aria-expanded', $dropdown.hasClass('active'));
          }
          // Try to keep drop-down menu within viewport
          if ($dropdown.hasClass('active')) {
            // Close any other open menus
            if ($('.prettydropdown > ul.active').length>1) {
              resetDropdown($('.prettydropdown > ul.active').not($dropdown));
              $('.prettydropdown > ul.active').not($dropdown).removeClass('active');
            }
            var nWinHeight = window.innerHeight,
              nMaxHeight,
              nOffsetTop = $dropdown.offset().top,
              nScrollTop = $(document).scrollTop(),
              nDropdownHeight = $dropdown.outerHeight();
            if (nSize) {
              nMaxHeight = nSize*(oOptions.height-2);
              if (nMaxHeight<nDropdownHeight-2) nDropdownHeight = nMaxHeight+2;
            }
            var nDropdownBottom = nOffsetTop-nScrollTop+nDropdownHeight;
            if (nDropdownBottom>nWinHeight) {
              // Expand to direction that has the most space
              if (nOffsetTop-nScrollTop>nWinHeight-(nOffsetTop-nScrollTop+oOptions.height)) {
                $dropdown.addClass('reverse');
                if (!oOptions.classic) $dropdown.append($selected);
                if (nOffsetTop-nScrollTop+oOptions.height<nDropdownHeight) {
                  $dropdown.outerHeight(nOffsetTop-nScrollTop+oOptions.height);
                  // Ensure the selected item is in view
                  $dropdown.scrollTop(nDropdownHeight);
                }
              } else {
                $dropdown.height($dropdown.height()-(nDropdownBottom-nWinHeight));
              }
            }
            if (nMaxHeight && nMaxHeight<$dropdown.height()) $dropdown.css('height', nMaxHeight + 'px');
            // Ensure the selected item is in view
            if (oOptions.classic) $dropdown.scrollTop($selected.index()*(oOptions.height-2));
          } else {
            $dropdown.data('clicked', true);
            resetDropdown($dropdown[0]);
          }
        });
        $dropdown.on({
          focusin: function() {
            // Unregister any existing handlers first to prevent duplicate firings
            $(window).off('keydown', handleKeypress).on('keydown', handleKeypress);
          },
          focusout: function() {
            $(window).off('keydown', handleKeypress);
          },
          mouseenter: function() {
            $dropdown.data('hover', true);
          },
          mouseleave: resetDropdown,
          mousemove:  hoverDropdownItem
        });
        if (oOptions.hoverIntent<0) {
          $(document).click(function(e) {
            if ($dropdown.data('hover') && !$dropdown[0].contains(e.target)) resetDropdown($dropdown[0]);
          });
        }
        // Put focus on menu when user clicks on label
        if (sLabelId) $('#' + sLabelId).off('click', handleFocus).click(handleFocus);
        // Done with everything!
        $dropdown.parent().width(oOptions.width||nOuterWidth||$dropdown.outerWidth(true)).removeClass('loading');
        oOptions.afterLoad();
      },

      // Manage widget focusing
      handleFocus = function(e) {
        $('ul[aria-labelledby=' + e.target.id + ']').focus();
      },

      // Manage keyboard navigation
      handleKeypress = function(e) {
        var $dropdown = $('.prettydropdown > ul.active, .prettydropdown > ul:focus');
        if (!$dropdown.length) return;
        if (e.which===9) { // Tab
          resetDropdown($dropdown[0]);
          return;
        } else {
          // Intercept non-Tab keys only
          e.preventDefault();
          e.stopPropagation();
        }
        var $items = $dropdown.children(),
          bOpen = $dropdown.hasClass('active'),
          nItemsHeight = $dropdown.height()/(oOptions.height-2),
          nItemsPerPage = nItemsHeight%1<0.5 ? Math.floor(nItemsHeight) : Math.ceil(nItemsHeight),
          sKey;
        nHoverIndex = Math.max(0, $dropdown.children('.hover').index());
        nLastIndex = $items.length-1;
        $current = $items.eq(nHoverIndex);
        $dropdown.data('lastKeypress', +new Date());
        switch (e.which) {
          case 13: // Enter
            if (!bOpen) {
              $current = $items.filter('.selected');
              toggleHover($current, 1);
            }
            $current.click();
            break;
          case 27: // Esc
            if (bOpen) resetDropdown($dropdown[0]);
            break;
          case 32: // Space
            if (bOpen) {
              sKey = ' ';
            } else {
              $current = $items.filter('.selected');
              toggleHover($current, 1);
              $current.click();
            }
            break;
          case 33: // Page Up
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(Math.max(nHoverIndex-nItemsPerPage-1, 0)), 1);
            }
            break;
          case 34: // Page Down
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(Math.min(nHoverIndex+nItemsPerPage-1, nLastIndex)), 1);
            }
            break;
          case 35: // End
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(nLastIndex), 1);
            }
            break;
          case 36: // Home
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(0), 1);
            }
            break;
          case 38: // Up
            if (bOpen) {
              toggleHover($current, 0);
              // If not already key-navigated or first item is selected, cycle to the last item; or
              // else select the previous item
              toggleHover(nHoverIndex ? $items.eq(nHoverIndex-1) : $items.eq(nLastIndex), 1);
            }
            break;
          case 40: // Down
            if (bOpen) {
              toggleHover($current, 0);
              // If last item is selected, cycle to the first item; or else select the next item
              toggleHover(nHoverIndex===nLastIndex ? $items.eq(0) : $items.eq(nHoverIndex+1), 1);
            }
            break;
          default:
            if (bOpen) sKey = aKeys[e.which-48];
        }
        if (sKey) { // Alphanumeric key pressed
          clearTimeout(nTimer);
          $dropdown.data('keysPressed', $dropdown.data('keysPressed')===undefined ? sKey : $dropdown.data('keysPressed') + sKey);
          nTimer = setTimeout(function() {
            $dropdown.removeData('keysPressed');
            // NOTE: Windows keyboard repeat delay is 250-1000 ms. See
            // https://technet.microsoft.com/en-us/library/cc978658.aspx
          }, 300);
          // Build index of matches
          var aMatches = [],
            nCurrentIndex = $current.index();
          $items.each(function(nIndex) {
            if ($(this).text().toLowerCase().indexOf($dropdown.data('keysPressed'))===0) aMatches.push(nIndex);
          });
          if (aMatches.length) {
            // Cycle through items matching key(s) pressed
            for (var i=0; i<aMatches.length; ++i) {
              if (aMatches[i]>nCurrentIndex) {
                toggleHover($items, 0);
                toggleHover($items.eq(aMatches[i]), 1);
                break;
              }
              if (i===aMatches.length-1) {
                toggleHover($items, 0);
                toggleHover($items.eq(aMatches[0]), 1);
              }
            }
          }
        }
      },

      // Highlight menu item
      hoverDropdownItem = function(e) {
        var $dropdown = $(e.currentTarget);
        if (e.target.nodeName!=='LI' || !$dropdown.hasClass('active') || new Date()-$dropdown.data('lastKeypress')<200) return;
        toggleHover($dropdown.children(), 0, 1);
        toggleHover($(e.target), 1, 1);
      },

      // Construct menu item
      // elOpt is null for first item in multi-select menus
      renderItem = function(elOpt, sClass, bSelected) {
        var sGroup = '',
          sText = '',
          sTitle;
        sClass = sClass || '';
        if (elOpt) {
          switch (elOpt.nodeName) {
            case 'OPTION':
              if (elOpt.parentNode.nodeName==='OPTGROUP') sGroup = elOpt.parentNode.getAttribute('label');
              sText = (elOpt.getAttribute('data-prefix') || '') + elOpt.text + (elOpt.getAttribute('data-suffix') || '');
              break;
            case 'OPTGROUP':
              sClass += ' label';
              sText = (elOpt.getAttribute('data-prefix') || '') + elOpt.getAttribute('label') + (elOpt.getAttribute('data-suffix') || '');
              break;
          }
         // if (elOpt.disabled || (sGroup && elOpt.parentNode.disabled)) sClass += ' disabled';
          sTitle = elOpt.title;
          if (sGroup && !sTitle) sTitle = elOpt.parentNode.title;
        }
        ++nCount;
        return '<li id="item' + nTimestamp + '-' + nCount + '"'
          + (sGroup ? ' data-group="' + sGroup + '"' : '')
          + (elOpt && (elOpt.value||oOptions.classic) ? ' data-value="' + elOpt.value.replace(/"/g, '″') + '"' : '')
          + (elOpt && elOpt.nodeName==='OPTION' ? ' role="option"' : '')
          + (sTitle ? ' title="' + sTitle + '" aria-label="' + sTitle + '"' : '')
          + (sClass ? ' class="' + $.trim(sClass) + '"' : '')
          + ((oOptions.height!==50) ? ' style="height:' + (oOptions.height-2)
          + 'px;line-height:' + (oOptions.height-4) + 'px;"' : '') + '>' + sText
          + ((bSelected || sClass==='selected') ? oOptions.selectedMarker : '') + '</li>';
      },

      // Reset menu state
      // @param o Event or Element object
      resetDropdown = function(o) {
        if (oOptions.hoverIntent<0 && o.type==='mouseleave') return;
        var $dropdown = $(o.currentTarget||o);
        $dropdown.data('hover', false);
        clearTimeout(nTimer);
        nTimer = setTimeout(function() {
          if ($dropdown.data('hover')) return;
          if ($dropdown.hasClass('reverse') && !oOptions.classic) $dropdown.prepend($dropdown.children(':last-child'));
          $dropdown.removeClass('active reverse').removeData('clicked').attr('aria-expanded', 'false').css('height', '');
          $dropdown.children().removeClass('hover nohover');
          // Update focus for NVDA screen readers
          $dropdown.attr('aria-activedescendant', $dropdown.children('.selected').attr('id'));
        }, (o.type==='mouseleave' && !$dropdown.data('clicked')) ? oOptions.hoverIntent : 0);
      },

      // Set menu item hover state
      // bNoScroll set on hoverDropdownItem()
      toggleHover = function($li, bOn, bNoScroll) {
        if (bOn) {
          var $dropdown = $li.parent();
          $li.removeClass('nohover').addClass('hover');
          // Update focus for NVDA screen readers
          $dropdown.attr('aria-activedescendant', $li.attr('id'));
          if ($li.length===1 && $current && !bNoScroll) {
            // Ensure items are always in view
            var nDropdownHeight = $dropdown.outerHeight(),
              nItemOffset = $li.offset().top-$dropdown.offset().top-1; // -1px for top border
            if ($li.index()===0) {
              $dropdown.scrollTop(0);
            } else if ($li.index()===nLastIndex) {
              $dropdown.scrollTop($dropdown.children().length*oOptions.height);
            } else {
              if (nItemOffset+oOptions.height>nDropdownHeight) $dropdown.scrollTop($dropdown.scrollTop()+oOptions.height+nItemOffset-nDropdownHeight);
              else if (nItemOffset<0) $dropdown.scrollTop($dropdown.scrollTop()+nItemOffset);
            }
          }
        } else {
          $li.removeClass('hover').addClass('nohover');
        }
      },

      // Update selected values for multi-select menu
      updateSelected = function($dropdown) {
        var $select = $dropdown.parent().children('select'),
          aSelected = $('option', $select).map(function() {
            if (this.selected) return this.text;
          }).get(),
          sSelected;
        if (oOptions.multiVerbosity>=aSelected.length) sSelected = aSelected.join(oOptions.multiDelimiter) || MULTI_NONE;
        else sSelected = aSelected.length + '/' + $('option', $select).length + MULTI_POSTFIX;
        if (sSelected) {
          var sTitle = ($select.attr('title') ? $select.attr('title') : '') + (aSelected.length ? '\n' + MULTI_PREFIX + aSelected.join(oOptions.multiDelimiter) : '');
          $dropdown.children('.selected').text(sSelected);
          $dropdown.attr({
            'title': sTitle,
            'aria-label': sTitle
          });
        } else {
          $dropdown.children('.selected').empty();
          $dropdown.attr({
            'title': $select.attr('title'),
            'aria-label': $select.attr('title')
          });
        }
      };
    
setTimeout(function(){  
  $('.variant-input-wrap').find('li').click(function() {
     changetext($(this));
  })
  changetext($('.variant-input-wrap').eq(0).find('li').eq(0));

  $('.stock-message').ready(function() {
     stockMessage($(this));
  })
},1000)

function stockMessage() {
  // var variant_message = $('.variant-wrapper').last().find('.variant-message').html();
   
  // $('.hidden-variant option').first().ready(function() {    
  //   if($(this).attr('data-available')=='true') {
  //     $('.stock-message').html("<span class='variant-label'>" + "In Stock" + "</span>");    
  //   } else {
  //     $('.stock-message').html("<span class='variant-label'>" + "Custom Made" + "</span>" + "<span class='variant-message'>" + variant_message + "</span>");
  //   }
  // });
}
    
function changetext(element){
  var current_option = element.attr('data-value'); 
   
  document.addEventListener('variant:change', function(event) {    
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");    
    } else if($.trim($('.prettydropdown li.selected .variant-message').html())!='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    }
  }.bind(this));
  
  setTimeout(function(){
    $('.variant-input-wrap').last().find('li').each(function(){
      if( $('.variant-input-wrap').eq(2).length > 0){
        var first_option = $('.variant-input-wrap').eq(0).find('.selected').attr('data-value');
        var second_option = $('.variant-input-wrap').eq(1).find('.selected').attr('data-value');
        var current_elem = $(this); 
        var unavailable = false;
        $('.hidden-variant option').each(function(){
          if($(this).attr('value') == first_option + ' / ' + second_option + ' / ' + current_elem.attr('data-value') && $(this).attr('data-available') == 'true'){ 
            current_elem.html(current_elem.attr('data-value') + '<span class="variant-label">In Stock</span>');
            unavailable = true;
          }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value') + '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">' + $('.hidden-variant option').attr('data-text') + '</span>');
        }
      }
      else if( $('.variant-input-wrap').eq(1).length > 0){
        var first_option = $('.variant-input-wrap').eq(0).find('.selected').attr('data-value');
        var current_elem = $(this);
        var unavailable = false;
        $('.hidden-variant option').each(function(){
          if($(this).attr('value') == first_option +' / ' + current_elem.attr('data-value') && $(this).attr('data-available') == 'true'){
            current_elem.html(current_elem.attr('data-value') + '<span class="variant-label">In Stock</span>');
            unavailable = true;
          }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value') + '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">' + $('.hidden-variant option').attr('data-text') + '</span>');
        }
      }
      else{
        var current_elem = $(this);
        var option_value = $(this).attr('data-value');
        var unavailable = false;
        $('.hidden-variant option').each(function(){
            if($(this).attr('value') == option_value && $(this).attr('data-available') == 'true'){
              current_elem.html(option_value+ '<span class="variant-label">In Stock</span>');
              unavailable = true;
            }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value')+ '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">'+$('.hidden-variant option').attr('data-text')+'</span>');
        }
      }
    })

    // update default
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");    
    } else if($.trim($('.prettydropdown li.selected .variant-message').html())!='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    }
  },500)
}
    
    /**
     * Public Functions
     */

    // Resync the menu with <select> to reflect state changes
    this.refresh = function(oOptions) {
      return this.each(function() {
        var $select = $(this);
        $select.prevAll('ul').remove();
        $select.unwrap().data('loaded', false);
        this.size = $select.data('size');
        init(this);
      });
    };

    return this.each(function() {
      init(this);
    });

  };
}(jQuery));
LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com
michaelmorgan
Shopify Partner
32 2 5

This works perfectly for products with multiple variants. Only issue now are products with no variants like this one display as 'undefined'

LitExtension
Shopify Partner
4901 1004 1176

This is an accepted solution.

Hi @michaelmorgan,

Please change all code:

/*!
 * jQuery Pretty Dropdowns Plugin v4.17.0 by T. H. Doan (https://thdoan.github.io/pretty-dropdowns/)
 *
 * jQuery Pretty Dropdowns by T. H. Doan is licensed under the MIT License.
 * Read a copy of the license in the LICENSE file or at https://choosealicense.com/licenses/mit/
 */

(function($) {
  $.fn.prettyDropdown = function(oOptions) {

    // Default options
    oOptions = $.extend({
      classic: true,
      customClass: 'arrow',
      width: null,
      height: 50,
      hoverIntent: -1,
      multiDelimiter: '; ',
      multiVerbosity: 99,
      selectedMarker: '&#10003;',
      afterLoad: function(){}
    }, oOptions);

    oOptions.selectedMarker = '<span aria-hidden="true" class="checked"> ' + oOptions.selectedMarker + '</span>';
    
    // Validate options
    if (isNaN(oOptions.width) && !/^\d+%$/.test(oOptions.width)) oOptions.width = null;
    if (isNaN(oOptions.height)) oOptions.height = 50;
    else if (oOptions.height<8) oOptions.height = 8;
    if (isNaN(oOptions.hoverIntent)) oOptions.hoverIntent = 200;
    if (isNaN(oOptions.multiVerbosity)) oOptions.multiVerbosity = 99;

    // Translatable strings
    var MULTI_NONE = 'None selected',
      MULTI_PREFIX = 'Selected: ',
      MULTI_POSTFIX = ' selected';

    // Globals
    var $current,
      aKeys = [
        '0','1','2','3','4','5','6','7','8','9',,,,,,,,
        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
      ],
      nCount,
      nHoverIndex,
      nLastIndex,
      nTimer,
      nTimestamp,

      // Initiate pretty drop-downs
      init = function(elSel) {
        var $select = $(elSel),
          nSize = elSel.size,
          sId = elSel.name || elSel.id || '',
          sLabelId;
        // Exit if widget has already been initiated
        if ($select.data('loaded')) return;
        // Remove 'size' attribute to it doesn't affect vertical alignment
        $select.data('size', nSize).removeAttr('size');
        // Set <select> height to reserve space for <div> container
        $select.css('display', 'none').outerHeight(oOptions.height);
        nTimestamp = performance.now()*100000000000000;
        // Test whether to add 'aria-labelledby'
        if (elSel.id) {
          // Look for <label>
          var $label = $('label[for=' + elSel.id + ']');
          if ($label.length) {
            // Add 'id' to <label> if necessary
            if ($label.attr('id') && !/^menu\d{13,}$/.test($label.attr('id'))) sLabelId = $label.attr('id');
            else $label.attr('id', (sLabelId = 'menu' + nTimestamp));
          }
        }
        nCount = 0;
        var $items = $('optgroup, option', $select),
          $selected = $items.filter(':selected'),
          bMultiple = elSel.multiple,
          // Height - 2px for borders
          sHtml = '<ul' + (elSel.disabled ? '' : ' tabindex="0"') + ' role="listbox"'
            + (elSel.title ? ' title="' + elSel.title + '" aria-label="' + elSel.title + '"' : '')
            + (sLabelId ? ' aria-labelledby="' + sLabelId + '"' : '')
            + ' aria-activedescendant="item' + nTimestamp + '-1" aria-expanded="false"'
            + ' style="max-height:' + (oOptions.height-2) + 'px;margin:'
            // NOTE: $select.css('margin') returns an empty string in Firefox, so we have to get
            // each margin individually. See https://github.com/jquery/jquery/issues/3383
            + $select.css('margin-top') + ' '
            + $select.css('margin-right') + ' '
            + $select.css('margin-bottom') + ' '
            + $select.css('margin-left') + ';">';
        if (bMultiple) {
          sHtml += renderItem(null, 'selected');
          $items.each(function() {
            if (this.selected) {
              sHtml += renderItem(this, '', true)
            } else {
              sHtml += renderItem(this);
            }
          });
        } else {
          if (oOptions.classic) {
            $items.each(function() {
              sHtml += renderItem(this);
            });
          } else {
            sHtml += renderItem($selected[0], 'selected');
            $items.filter(':not(:selected)').each(function() {
              sHtml += renderItem(this);
            });
          }
        }
        sHtml += '</ul>';
        $select.wrap('<div ' + (sId ? 'id="prettydropdown-' + sId + '" ' : '')
          + 'class="prettydropdown '
          + (oOptions.classic ? 'classic ' : '')
          + (elSel.disabled ? 'disabled ' : '')
          + (bMultiple ? 'multiple ' : '')
          + oOptions.customClass + ' loading"'
          // NOTE: For some reason, the container height is larger by 1px if the <select> has the
          // 'multiple' attribute or 'size' attribute with a value larger than 1. To fix this, we
          // have to inline the height.
          + ((bMultiple || nSize>1) ? ' style="height:' + oOptions.height + 'px;"' : '')
          +'></div>').before(sHtml).data('loaded', true);
        var $dropdown = $select.parent().children('ul'),
          nWidth = $dropdown.outerWidth(true),
          nOuterWidth;
        $items = $dropdown.children();
        // Update default selected values for multi-select menu
        if (bMultiple) updateSelected($dropdown);
        else if (oOptions.classic) $('[data-value="' + $selected.val().replace(/"/g, '″') + '"]', $dropdown).addClass('selected').append(oOptions.selectedMarker);
        // Calculate width if initially hidden
        if ($dropdown.width()<=0) {
          var $clone = $dropdown.parent().clone().css({
              position: 'absolute',
              top: '-100%'
            });
            $('body').append($clone);
            nWidth = $clone.children('ul').outerWidth(true);
            $('li', $clone).width(nWidth);
            nOuterWidth = $clone.children('ul').outerWidth(true);
            $clone.remove();
        }
        // Set dropdown width and event handler
        // NOTE: Setting width using width(), then css() because width() only can return a float,
        // which can result in a missing right border when there is a scrollbar.
        $items.width(nWidth).css('width', $items.css('width'));
        if (oOptions.width) {
          $dropdown.parent().css('min-width', $items.css('width'));
          $dropdown.css('width', '100%');
          $items.css('width', '100%');
        }
        $items.click(function() {
          var $li = $(this),
            $selected = $dropdown.children('.selected');
          // Ignore disabled menu
          if ($dropdown.parent().hasClass('disabled')) return;
          // Only update if not disabled, not a label, and a different value selected
          if ($dropdown.hasClass('active') && !$li.hasClass('disabled') && !$li.hasClass('label') && $li.data('value').toString().replace(/"/g, '″')!==$selected.data('value').toString().replace(/"/g, '″')) {
            // Select highlighted item
            if (bMultiple) {
              if ($li.children('span.checked').length) $li.children('span.checked').remove();
              else $li.append(oOptions.selectedMarker);
              // Sync <select> element
              $dropdown.children(':not(.selected)').each(function(nIndex) {
                $('optgroup, option', $select).eq(nIndex).prop('selected', $(this).children('span.checked').length>0);
              });
              // Update selected values for multi-select menu
              updateSelected($dropdown);
            } else {
              $selected.removeClass('selected').children('span.checked').remove();
              $li.addClass('selected').append(oOptions.selectedMarker);
              if (!oOptions.classic) $dropdown.prepend($li);
              $dropdown.removeClass('reverse').attr('aria-activedescendant', $li.attr('id'));
              if ($selected.data('group') && !oOptions.classic) $dropdown.children('.label').filter(function() {
                return $(this).text()===$selected.data('group');
              }).after($selected);
              // Sync <select> element
              $('optgroup, option', $select).filter(function() {
                // <option>: this.value = this.text, $li.data('value') = $li.contents()
                // <option value="">: this.value = "", $li.data('value') = undefined
                return (this.value.replace(/"/g, '″')+'|'+this.text.replace(/"/g, '″'))===($li.data('value')||'')+'|'+$li.contents().filter(function() {
                    // Filter out selected marker
                    return this.nodeType===3;
                  }).text();
              }).prop('selected', true);
            }
            $select.get(0).dispatchEvent(new Event('change'))
          }
          if ($li.hasClass('selected') || !bMultiple) {
            $dropdown.toggleClass('active');
            $dropdown.attr('aria-expanded', $dropdown.hasClass('active'));
          }
          // Try to keep drop-down menu within viewport
          if ($dropdown.hasClass('active')) {
            // Close any other open menus
            if ($('.prettydropdown > ul.active').length>1) {
              resetDropdown($('.prettydropdown > ul.active').not($dropdown));
              $('.prettydropdown > ul.active').not($dropdown).removeClass('active');
            }
            var nWinHeight = window.innerHeight,
              nMaxHeight,
              nOffsetTop = $dropdown.offset().top,
              nScrollTop = $(document).scrollTop(),
              nDropdownHeight = $dropdown.outerHeight();
            if (nSize) {
              nMaxHeight = nSize*(oOptions.height-2);
              if (nMaxHeight<nDropdownHeight-2) nDropdownHeight = nMaxHeight+2;
            }
            var nDropdownBottom = nOffsetTop-nScrollTop+nDropdownHeight;
            if (nDropdownBottom>nWinHeight) {
              // Expand to direction that has the most space
              if (nOffsetTop-nScrollTop>nWinHeight-(nOffsetTop-nScrollTop+oOptions.height)) {
                $dropdown.addClass('reverse');
                if (!oOptions.classic) $dropdown.append($selected);
                if (nOffsetTop-nScrollTop+oOptions.height<nDropdownHeight) {
                  $dropdown.outerHeight(nOffsetTop-nScrollTop+oOptions.height);
                  // Ensure the selected item is in view
                  $dropdown.scrollTop(nDropdownHeight);
                }
              } else {
                $dropdown.height($dropdown.height()-(nDropdownBottom-nWinHeight));
              }
            }
            if (nMaxHeight && nMaxHeight<$dropdown.height()) $dropdown.css('height', nMaxHeight + 'px');
            // Ensure the selected item is in view
            if (oOptions.classic) $dropdown.scrollTop($selected.index()*(oOptions.height-2));
          } else {
            $dropdown.data('clicked', true);
            resetDropdown($dropdown[0]);
          }
        });
        $dropdown.on({
          focusin: function() {
            // Unregister any existing handlers first to prevent duplicate firings
            $(window).off('keydown', handleKeypress).on('keydown', handleKeypress);
          },
          focusout: function() {
            $(window).off('keydown', handleKeypress);
          },
          mouseenter: function() {
            $dropdown.data('hover', true);
          },
          mouseleave: resetDropdown,
          mousemove:  hoverDropdownItem
        });
        if (oOptions.hoverIntent<0) {
          $(document).click(function(e) {
            if ($dropdown.data('hover') && !$dropdown[0].contains(e.target)) resetDropdown($dropdown[0]);
          });
        }
        // Put focus on menu when user clicks on label
        if (sLabelId) $('#' + sLabelId).off('click', handleFocus).click(handleFocus);
        // Done with everything!
        $dropdown.parent().width(oOptions.width||nOuterWidth||$dropdown.outerWidth(true)).removeClass('loading');
        oOptions.afterLoad();
      },

      // Manage widget focusing
      handleFocus = function(e) {
        $('ul[aria-labelledby=' + e.target.id + ']').focus();
      },

      // Manage keyboard navigation
      handleKeypress = function(e) {
        var $dropdown = $('.prettydropdown > ul.active, .prettydropdown > ul:focus');
        if (!$dropdown.length) return;
        if (e.which===9) { // Tab
          resetDropdown($dropdown[0]);
          return;
        } else {
          // Intercept non-Tab keys only
          e.preventDefault();
          e.stopPropagation();
        }
        var $items = $dropdown.children(),
          bOpen = $dropdown.hasClass('active'),
          nItemsHeight = $dropdown.height()/(oOptions.height-2),
          nItemsPerPage = nItemsHeight%1<0.5 ? Math.floor(nItemsHeight) : Math.ceil(nItemsHeight),
          sKey;
        nHoverIndex = Math.max(0, $dropdown.children('.hover').index());
        nLastIndex = $items.length-1;
        $current = $items.eq(nHoverIndex);
        $dropdown.data('lastKeypress', +new Date());
        switch (e.which) {
          case 13: // Enter
            if (!bOpen) {
              $current = $items.filter('.selected');
              toggleHover($current, 1);
            }
            $current.click();
            break;
          case 27: // Esc
            if (bOpen) resetDropdown($dropdown[0]);
            break;
          case 32: // Space
            if (bOpen) {
              sKey = ' ';
            } else {
              $current = $items.filter('.selected');
              toggleHover($current, 1);
              $current.click();
            }
            break;
          case 33: // Page Up
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(Math.max(nHoverIndex-nItemsPerPage-1, 0)), 1);
            }
            break;
          case 34: // Page Down
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(Math.min(nHoverIndex+nItemsPerPage-1, nLastIndex)), 1);
            }
            break;
          case 35: // End
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(nLastIndex), 1);
            }
            break;
          case 36: // Home
            if (bOpen) {
              toggleHover($current, 0);
              toggleHover($items.eq(0), 1);
            }
            break;
          case 38: // Up
            if (bOpen) {
              toggleHover($current, 0);
              // If not already key-navigated or first item is selected, cycle to the last item; or
              // else select the previous item
              toggleHover(nHoverIndex ? $items.eq(nHoverIndex-1) : $items.eq(nLastIndex), 1);
            }
            break;
          case 40: // Down
            if (bOpen) {
              toggleHover($current, 0);
              // If last item is selected, cycle to the first item; or else select the next item
              toggleHover(nHoverIndex===nLastIndex ? $items.eq(0) : $items.eq(nHoverIndex+1), 1);
            }
            break;
          default:
            if (bOpen) sKey = aKeys[e.which-48];
        }
        if (sKey) { // Alphanumeric key pressed
          clearTimeout(nTimer);
          $dropdown.data('keysPressed', $dropdown.data('keysPressed')===undefined ? sKey : $dropdown.data('keysPressed') + sKey);
          nTimer = setTimeout(function() {
            $dropdown.removeData('keysPressed');
            // NOTE: Windows keyboard repeat delay is 250-1000 ms. See
            // https://technet.microsoft.com/en-us/library/cc978658.aspx
          }, 300);
          // Build index of matches
          var aMatches = [],
            nCurrentIndex = $current.index();
          $items.each(function(nIndex) {
            if ($(this).text().toLowerCase().indexOf($dropdown.data('keysPressed'))===0) aMatches.push(nIndex);
          });
          if (aMatches.length) {
            // Cycle through items matching key(s) pressed
            for (var i=0; i<aMatches.length; ++i) {
              if (aMatches[i]>nCurrentIndex) {
                toggleHover($items, 0);
                toggleHover($items.eq(aMatches[i]), 1);
                break;
              }
              if (i===aMatches.length-1) {
                toggleHover($items, 0);
                toggleHover($items.eq(aMatches[0]), 1);
              }
            }
          }
        }
      },

      // Highlight menu item
      hoverDropdownItem = function(e) {
        var $dropdown = $(e.currentTarget);
        if (e.target.nodeName!=='LI' || !$dropdown.hasClass('active') || new Date()-$dropdown.data('lastKeypress')<200) return;
        toggleHover($dropdown.children(), 0, 1);
        toggleHover($(e.target), 1, 1);
      },

      // Construct menu item
      // elOpt is null for first item in multi-select menus
      renderItem = function(elOpt, sClass, bSelected) {
        var sGroup = '',
          sText = '',
          sTitle;
        sClass = sClass || '';
        if (elOpt) {
          switch (elOpt.nodeName) {
            case 'OPTION':
              if (elOpt.parentNode.nodeName==='OPTGROUP') sGroup = elOpt.parentNode.getAttribute('label');
              sText = (elOpt.getAttribute('data-prefix') || '') + elOpt.text + (elOpt.getAttribute('data-suffix') || '');
              break;
            case 'OPTGROUP':
              sClass += ' label';
              sText = (elOpt.getAttribute('data-prefix') || '') + elOpt.getAttribute('label') + (elOpt.getAttribute('data-suffix') || '');
              break;
          }
         // if (elOpt.disabled || (sGroup && elOpt.parentNode.disabled)) sClass += ' disabled';
          sTitle = elOpt.title;
          if (sGroup && !sTitle) sTitle = elOpt.parentNode.title;
        }
        ++nCount;
        return '<li id="item' + nTimestamp + '-' + nCount + '"'
          + (sGroup ? ' data-group="' + sGroup + '"' : '')
          + (elOpt && (elOpt.value||oOptions.classic) ? ' data-value="' + elOpt.value.replace(/"/g, '″') + '"' : '')
          + (elOpt && elOpt.nodeName==='OPTION' ? ' role="option"' : '')
          + (sTitle ? ' title="' + sTitle + '" aria-label="' + sTitle + '"' : '')
          + (sClass ? ' class="' + $.trim(sClass) + '"' : '')
          + ((oOptions.height!==50) ? ' style="height:' + (oOptions.height-2)
          + 'px;line-height:' + (oOptions.height-4) + 'px;"' : '') + '>' + sText
          + ((bSelected || sClass==='selected') ? oOptions.selectedMarker : '') + '</li>';
      },

      // Reset menu state
      // @param o Event or Element object
      resetDropdown = function(o) {
        if (oOptions.hoverIntent<0 && o.type==='mouseleave') return;
        var $dropdown = $(o.currentTarget||o);
        $dropdown.data('hover', false);
        clearTimeout(nTimer);
        nTimer = setTimeout(function() {
          if ($dropdown.data('hover')) return;
          if ($dropdown.hasClass('reverse') && !oOptions.classic) $dropdown.prepend($dropdown.children(':last-child'));
          $dropdown.removeClass('active reverse').removeData('clicked').attr('aria-expanded', 'false').css('height', '');
          $dropdown.children().removeClass('hover nohover');
          // Update focus for NVDA screen readers
          $dropdown.attr('aria-activedescendant', $dropdown.children('.selected').attr('id'));
        }, (o.type==='mouseleave' && !$dropdown.data('clicked')) ? oOptions.hoverIntent : 0);
      },

      // Set menu item hover state
      // bNoScroll set on hoverDropdownItem()
      toggleHover = function($li, bOn, bNoScroll) {
        if (bOn) {
          var $dropdown = $li.parent();
          $li.removeClass('nohover').addClass('hover');
          // Update focus for NVDA screen readers
          $dropdown.attr('aria-activedescendant', $li.attr('id'));
          if ($li.length===1 && $current && !bNoScroll) {
            // Ensure items are always in view
            var nDropdownHeight = $dropdown.outerHeight(),
              nItemOffset = $li.offset().top-$dropdown.offset().top-1; // -1px for top border
            if ($li.index()===0) {
              $dropdown.scrollTop(0);
            } else if ($li.index()===nLastIndex) {
              $dropdown.scrollTop($dropdown.children().length*oOptions.height);
            } else {
              if (nItemOffset+oOptions.height>nDropdownHeight) $dropdown.scrollTop($dropdown.scrollTop()+oOptions.height+nItemOffset-nDropdownHeight);
              else if (nItemOffset<0) $dropdown.scrollTop($dropdown.scrollTop()+nItemOffset);
            }
          }
        } else {
          $li.removeClass('hover').addClass('nohover');
        }
      },

      // Update selected values for multi-select menu
      updateSelected = function($dropdown) {
        var $select = $dropdown.parent().children('select'),
          aSelected = $('option', $select).map(function() {
            if (this.selected) return this.text;
          }).get(),
          sSelected;
        if (oOptions.multiVerbosity>=aSelected.length) sSelected = aSelected.join(oOptions.multiDelimiter) || MULTI_NONE;
        else sSelected = aSelected.length + '/' + $('option', $select).length + MULTI_POSTFIX;
        if (sSelected) {
          var sTitle = ($select.attr('title') ? $select.attr('title') : '') + (aSelected.length ? '\n' + MULTI_PREFIX + aSelected.join(oOptions.multiDelimiter) : '');
          $dropdown.children('.selected').text(sSelected);
          $dropdown.attr({
            'title': sTitle,
            'aria-label': sTitle
          });
        } else {
          $dropdown.children('.selected').empty();
          $dropdown.attr({
            'title': $select.attr('title'),
            'aria-label': $select.attr('title')
          });
        }
      };
    
setTimeout(function(){  
  $('.variant-input-wrap').find('li').click(function() {
     changetext($(this));
  })
  changetext($('.variant-input-wrap').eq(0).find('li').eq(0));

  $('.stock-message').ready(function() {
     stockMessage($(this));
  })
},1000)

function stockMessage() {
  // var variant_message = $('.variant-wrapper').last().find('.variant-message').html();
   
  // $('.hidden-variant option').first().ready(function() {    
  //   if($(this).attr('data-available')=='true') {
  //     $('.stock-message').html("<span class='variant-label'>" + "In Stock" + "</span>");    
  //   } else {
  //     $('.stock-message').html("<span class='variant-label'>" + "Custom Made" + "</span>" + "<span class='variant-message'>" + variant_message + "</span>");
  //   }
  // });
}
    
function changetext(element){
  var current_option = element.attr('data-value'); 
   
  document.addEventListener('variant:change', function(event) {    
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");    
    } else if($.trim($('.prettydropdown li.selected .variant-message').html())!='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    }
  }.bind(this));
  
  setTimeout(function(){
    $('.variant-input-wrap').last().find('li').each(function(){
      if( $('.variant-input-wrap').eq(2).length > 0){
        var first_option = $('.variant-input-wrap').eq(0).find('.selected').attr('data-value');
        var second_option = $('.variant-input-wrap').eq(1).find('.selected').attr('data-value');
        var current_elem = $(this); 
        var unavailable = false;
        $('.hidden-variant option').each(function(){
          if($(this).attr('value') == first_option + ' / ' + second_option + ' / ' + current_elem.attr('data-value') && $(this).attr('data-available') == 'true'){ 
            current_elem.html(current_elem.attr('data-value') + '<span class="variant-label">In Stock</span>');
            unavailable = true;
          }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value') + '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">' + $('.hidden-variant option').attr('data-text') + '</span>');
        }
      }
      else if( $('.variant-input-wrap').eq(1).length > 0){
        var first_option = $('.variant-input-wrap').eq(0).find('.selected').attr('data-value');
        var current_elem = $(this);
        var unavailable = false;
        $('.hidden-variant option').each(function(){
          if($(this).attr('value') == first_option +' / ' + current_elem.attr('data-value') && $(this).attr('data-available') == 'true'){
            current_elem.html(current_elem.attr('data-value') + '<span class="variant-label">In Stock</span>');
            unavailable = true;
          }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value') + '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">' + $('.hidden-variant option').attr('data-text') + '</span>');
        }
      }
      else{
        var current_elem = $(this);
        var option_value = $(this).attr('data-value');
        var unavailable = false;
        $('.hidden-variant option').each(function(){
            if($(this).attr('value') == option_value && $(this).attr('data-available') == 'true'){
              current_elem.html(option_value+ '<span class="variant-label">In Stock</span>');
              unavailable = true;
            }
        })
        if(!unavailable){
          current_elem.html($(this).attr('data-value')+ '<span class="variant-label">Custom Made</span>'+ '<span class="variant-message">'+$('.hidden-variant option').attr('data-text')+'</span>');
        }
      }
    })

    // update default
    if($.trim($('.prettydropdown li.selected .variant-message').html())=='') {
      $('.stock-message').html("In Stock");    
    } else if($.trim($('.prettydropdown li.selected .variant-message').html())!='') {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    }
  },500)
}
    
    /**
     * Public Functions
     */

    // Resync the menu with <select> to reflect state changes
    this.refresh = function(oOptions) {
      return this.each(function() {
        var $select = $(this);
        $select.prevAll('ul').remove();
        $select.unwrap().data('loaded', false);
        this.size = $select.data('size');
        init(this);
      });
    };

    return this.each(function() {
      init(this);
    });

  };
}(jQuery));
LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com
michaelmorgan
Shopify Partner
32 2 5

There was an issue with some products that have a blank variant message but are still "Custom Made". I updated the code to the following to try and fix that, but I don't see how it would pull in the correct value when there is no variant dropdown. Wouldn't it need to pull the info from the '.hidden-variant'? This product has no variants. This product has multiple

 

 // update default
if($.trim($('.prettydropdown li.selected .variant-label').html())=='In Stock') {
$('.stock-message').html("In Stock");
} else if($.trim($('.prettydropdown li.selected .variant-label').html())=='Custom Made' && ($.trim($('.prettydropdown li.selected .variant-message').html())!='')) {
$('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
} else if($.trim($('.prettydropdown li.selected .variant-label').html())=='Custom Made' && ($.trim($('.prettydropdown li.selected .variant-message').html())=='')) {
$('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");
}
},500)

 

 

LitExtension
Shopify Partner
4901 1004 1176

Hi @michaelmorgan,

Products without variants, will be updated here:

Screenshot.png

LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com
michaelmorgan
Shopify Partner
32 2 5

But the products with no variants don't have a '.prettydropdown li.selected .variant-label' since they don't have a dropdown. Wouldn't they need to pull the info from the '.hidden-variant' printed data? Like this product doesn't have a message displaying now.

LitExtension
Shopify Partner
4901 1004 1176

Hi @michaelmorgan,

Means you want to hide it, you just need to remove the following code, and it will work fine.

Screenshot.png

LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com
michaelmorgan
Shopify Partner
32 2 5

I am not sure what you are saying. I want to display the message on all products. I updated the code to the following. It now displays the message for products with no variants but now the issue is for the products that have variants, when you change the variant, it reverts the message to the value of the first option after the 500ms. So it looks like the '.hidden-variant option' (used for the products without variants) is overriding. I think the code for the products with variants and ones without should be separate but I am unsure how to go about that.

    // update default
    if($.trim($('.prettydropdown li.selected .variant-label').html())=='In Stock' || $('.hidden-variant option').attr('data-available')=='true') {
      $('.stock-message').html("<span class='variant-label'> In Stock </span>");    
    } else if($.trim($('.prettydropdown li.selected .variant-label').html())=='Custom Made' && ($.trim($('.prettydropdown li.selected .variant-message').html())!='')) {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    } else if($.trim($('.prettydropdown li.selected .variant-label').html())=='Custom Made' && ($.trim($('.prettydropdown li.selected .variant-message').html())=='')) {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");
    } else if($('.hidden-variant option').attr('data-available')=='false' && $('.hidden-variant option').attr('data-text')=='') {
      $('.stock-message').html("<span class='variant-label'> Custom Made </span>");
    } else if($('.hidden-variant option').attr('data-available')=='false' && $('.hidden-variant option').attr('data-text')!='') {
      $('.stock-message').html("<span class='variant-label'> Custom Made </span>" + "<span class='variant-message'>" + $('.hidden-variant option').attr('data-text') + "</span>");
    }
  },500)

.

michaelmorgan
Shopify Partner
32 2 5

Hey! I was messing around some more and added "$('.prettydropdown').length === 0" to the ".hidden-variant" parts and it worked like a charm. Its good to go now!

 

    // update default
    if($.trim($('.prettydropdown li.selected .variant-label').html())=='In Stock' || $('.hidden-variant option').attr('data-available')=='true' && $('.prettydropdown').length === 0) {
      $('.stock-message').html("<span class='variant-label'> In Stock </span>");    
    } else if($.trim($('.prettydropdown li.selected .variant-label').html())=='Custom Made' && ($.trim($('.prettydropdown li.selected .variant-message').html())!='')) {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>" + "<span class='variant-message'>" + $('.prettydropdown li.selected .variant-message').html() + "</span>");
    } else if($.trim($('.prettydropdown li.selected .variant-label').html())=='Custom Made' && ($.trim($('.prettydropdown li.selected .variant-message').html())=='')) {
      $('.stock-message').html("<span class='variant-label'>" + $('.prettydropdown li.selected .variant-label').html() + "</span>");
    } else if($('.hidden-variant option').attr('data-available')=='false' && $('.hidden-variant option').attr('data-text')=='' && $('.prettydropdown').length === 0) {
      $('.stock-message').html("<span class='variant-label'> Custom Made </span>");
    } else if($('.hidden-variant option').attr('data-available')=='false' && $('.hidden-variant option').attr('data-text')!='' && $('.prettydropdown').length === 0) {
      $('.stock-message').html("<span class='variant-label'> Custom Made </span>" + "<span class='variant-message'>" + $('.hidden-variant option').attr('data-text') + "</span>");
    }
  },500)

 

LitExtension
Shopify Partner
4901 1004 1176

Hi @michaelmorgan,

If it helped you solve your issue, please mark it as a solution. Thank you and good luck.

LitExtension - Shopping Cart Migration Expert
Check out our Shopify migration app to migrate your online store to Shopify
Contact us:
- Email: contact@litextension.com

RieDet
Visitor
1 0 0

Hello Sir/Madam,

 

I would like to know about Shopify operate in Cambodia.

How it work ?