Я вижу несколько проблем:
- Вы не конвертируете "Келли Грин" в "Келли".
- В
var new_src = $('#preload img[src*=keyword]');
жестко закодировано keyword
(не значение ключевой переменной).
- У
li
в списке нет элементов img
внутри (они просто содержат URL-адрес в виде текста). Вы отредактировали вопрос и исправили это .
- Если выбранное значение не является "Kelly Green", вы не делаете его строчным и совсем не используете значение.
- Вы не получаете атрибут
src
изображения предварительной загрузки.
Если вы измените список на:
<ul id="preload" style="display:none;">
<li><img src='0z-kelly-green-medium.jpg'></li>
<li><img src='0z-olive-medium.jpg'></li>
</ul>
(Это было частью того, что было исправлено.)
Тогда это должно работать:
jQuery(document).ready(function($) {
$('#product-variants-option-0').change(function() {
var select_value, keyword, new_src;
// What is the sku of the current variant selection
select_value = $(this).find(':selected').val();
// Get the keyword to use (the value in lower case, or "kelly" if the
// value is "Kelly Green")
keyword = select_value == "Kelly Green" ? "kelly" : select_value.toLowerCase();
// Find the image using that `src`, note that we concatenate the value
// from `keyword`, rather than having it in a literal.
new_src = $('#preload img[src*=' + keyword + ']').attr('src');
// Set the image's source.
$('div.image img').attr('src', new_src);
});
});
Живой пример
Чарльз, вы попросили дать информацию о том, как это может быть написано по-другому, и я сказал, что у меня есть минутка, чтобы что-то сделать. Извините за задержку, моя настоящая работа на мгновение понадобилась мне.
Я, вероятно, подхожу к этому следующим образом, предполагая, что у вас есть такой вид блока выбора в другом месте вашего приложения, и поэтому стоит обобщение.
- Делайте вещи многократно используемыми везде, где это возможно (ну, почти; есть одно обобщение, которое я оставил читателю в качестве упражнения).
- Не храните URL-адреса изображений в одном месте, а параметры в другом; собрать их вместе, чтобы они оба могли легко поступить из одного источника данных. Это уменьшает ошибку. (Например, в вашем вопросе у вас есть четыре варианта, но у вас есть только изображения для двух из них в структуре предварительной загрузки. Теперь, если у вас нет изображений для других, это нормально, оставьте атрибут выключенным или сделайте его пусто, но хранить все вместе / генерировать из одного источника - хорошая идея.)
- Сделайте # 2 с атрибутом
data-image
, который действителен с HTML5 и совершенно безвреден в более ранних версиях. ( Подробнее )
- Не включайте разметку для предварительной загрузки в HTML; генерировать это. Это относится к # 2, а также к тому факту, что пользователям, не имеющим JavaScript, не нужны предварительно кэшированные изображения, поскольку они не будут использоваться. Так что не заставляйте их делать то, что им не нужно.
HTML:
<select class="single-option-selector-0" id="product-variants-option-0">
<option
value="Kelly Green"
data-image="0z-kelly-green-medium.jpg"
>Kelly Green</option>
<option
value="Navy"
data-image="0z-navy-medium.jpg"
>Navy</option>
<option
value="Olive"
data-image="0z-olive-medium.jpg"
>Olive</option>
<option
value="Cocoa"
data-image="0z-cocoa-medium.jpg"
>Cocoa</option>
</select>
и
<div class='image'><img src='placeholder.jpg'></div>
JavaScript с jQuery:
(function($) {
// A utility function from my arsenal; you can
// just inline this if you don't want it.
// Returns an array containing the given attribute
// from *all* of the elements in the jQuery object.
// Args:
// name Name of the attribute to fetch
// blanksOkay (Optional, default false) true if
// you want blanks in the array for
// blank entries or non-existant entries;
// false if you want them left out.
$.fn.attrAll = function(name, blanksOkay) {
var list, index;
if (typeof blanksOkay === "undefined") {
blanksOkay = false;
}
list = [];
for (index = 0; index < this.length; ++index) {
entry = $(this[index]).attr(name);
if (entry || blanksOkay) {
list.push(entry);
}
}
return list;
};
})(jQuery);
// The page's ready script
jQuery(function($) {
// Set up the product variants select box.
// You could generalize this with classes or other attributes
// (so there would be *nothing* special about the select box),
// but I didn't want to change your markup too much.
setupSelectWithImages(
'#product-variants-option-0',
'div.image img:first'
);
// ===
// All of the following would probably be in your
// utility script; it's not page-specific.
// ===
// Set up our select box that's equipped with images
// so it shows the image when an option is selected.
// The options within the box should have data-image
// attributes for their images, which are precached.
// Args:
// boxSelector The selector that finds the select box
// targetSelector The selector that finds the target img
function setupSelectWithImages(boxSelector, targetSelector) {
var box;
// Get the select box
box = $(boxSelector);
// Preload the images
preloadImages(box.find('option'), 'data-image');
// Ensure we show the correct image when the select box
// changes, and force showing it right now for the default
// value.
setCurrentImage.call(box[0]);
box.change(setCurrentImage);
function setCurrentImage() {
var entry = $(this).find('option:selected').attr('data-image');
if (entry) {
display("Setting src to " + entry);
$(targetSelector).attr('src', entry);
}
}
// Done with box
box = undefined;
}
// Another general purpose function; preloads the images
// defined by the given attribute on the elements in the
// given jQuery object.
// I've kept things bundled up (in a div rather than a ul),
// but there's no special reason to, you could just add
// the individual images to the body directly.
// Using a container makes it easy to return a single
// thing out of this function, which may be useful
// to some calling code.
function preloadImages(list, attrName) {
var markup;
// Get a list of the relevant attribute
markup = list.attrAll('data-image');
// Convert it into a bunch of img tags
markup = joinEntries(markup, "<img src='", "'>");
// Put them in an off-page div, add it to the document,
// and return the div to the caller
return $("<div/>").css({
'position': 'absolute',
'left': '-10000px',
'top': '0px'
}).html(markup).appendTo(document.body);
}
// Join the entries in the array with the given
// prefix and suffix.
function joinEntries(a, prefix, suffix) {
prefix = prefix || '';
suffix = suffix || '';
return prefix + a.join(suffix + prefix) + suffix;
}
// This is just for our purposes in this demo
function display(msg) {
$("<p/>").html(msg).appendTo(document.body);
}
});
Живой пример (но в живом примере используются некоторые граватары, так что вы действительно можете видеть изображения)