Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to customize dropdown list (add images, etc) #16888

Open
rightaway opened this issue Apr 29, 2016 · 14 comments
Open

How to customize dropdown list (add images, etc) #16888

rightaway opened this issue Apr 29, 2016 · 14 comments
Labels

Comments

@rightaway
Copy link

In the dropdown list of suggestions, instead of just text appearing is it possible to have images next to the text? For example, if the dropdown contains a list of food, there could be a small picture of that food item next to it. Is it possible to do or could this feature be added?

@LeaVerou
Copy link
Owner

It is, as of v1.1!! @vlazar, could you explain how, since you added that feature?

@vlazar
Copy link
Collaborator

vlazar commented May 11, 2016

It may be possible, since we have separated label and value for each suggestion item in v1.1.

List of items provided via list property can be any object with properties like { label: ..., value: ..., url: ...}.

However, since we also support string based v1.0 API we wrap items internally with special Suggestion object. This object has only label and value properties from original item on the list (no url). So right now you can't just use url property in functions like item and others.

As workaround, if you only need text and image, you can use value for text and label for image url and define custom item function to show image in each suggestion.

@LeaVerou I think we should definitely try to extend Awesomplete for this case, so that any property in original list will be accessible in custom functions.

@TxHawks
Copy link
Contributor

TxHawks commented May 11, 2016

+1 for making all properties accessible

@vlazar
Copy link
Collaborator

vlazar commented May 12, 2016

@rightaway The following options should work for you then:

list: [ { value: 'Text for dropdown and input field', label: 'http://example.com/img.jpg' }, ...],

item: function (suggestion, input) {
    // notice the use of suggestion.value here, default function effectively uses suggestion.label
    var html = input === '' ? suggestion.value : suggestion.value.replace(RegExp($.regExpEscape(input), "gi"), "<mark>$&</mark>");

    // here you will have image URL in suggestion.label property, so you can add it to LI
    return $.create("li", {
        innerHTML: html,
        "aria-selected": "false"
    });
},

filter: function(suggestion, input) {
    // the default function uses suggestion.label here as well, so we need to override this too
    return Awesomplete.FILTER_STARTSWITH(suggestion.value, input);
}

@Insood
Copy link

Insood commented Jun 14, 2016

Hey guys, thanks for the script. This is what I ended up doing for my purposes:

AWESOMPLETES = {}

image_search_input_change = (e) ->
    element = this
    $.getJSON( "/images", {file: this.value}).success( (data) ->
        AWESOMPLETES[element].list = data
    )

configure_image_select = (index, obj) ->
    AWESOMPLETES[obj] =     new Awesomplete(obj, {
        minChars: 1
        maxItems: 15
        item: (suggestion, input) ->
            if input.length > 0
                label_parts = suggestion.split(":")
                img  = label_parts[0]
                file = label_parts[1]
                rest = label_parts.slice(2).join(":")

                mark = rest.replace(RegExp(Awesomplete.$.regExpEscape(input), "gi"), "<mark>$&</mark>");
                html = "<img src=\"#{img}\"}> <b>#{file}</b> :: " + mark

                return Awesomplete.$.create("li", {
                    innerHTML: html,
                    "aria-selected": "false"
                })
        filter: (item, input) ->
            text = item.split(":").slice(1).join(":")
            Awesomplete.FILTER_CONTAINS(text, input.match(/[^,]*$/)[0]);
    })


on_load = ->
    $('input.select_image_for_step').each(  configure_image_select )
    $('input.select_image_for_step').keyup( image_search_input_change )

$ ->
    on_load()

The data is in this format:

class ImagesController < ApplicationController
    def index
        respond_to do |format|
            format.html { prepare_for_index() }
            format.json do
                if params[:file] then
                    @images = Image.all
                    val = []
                    @images.each do |i|
                        val << {  value: i.id, label: "#{i.image_file.wi_thumb.url}:#{i.filename()}:#{i.description}"}
                    end
                    render( json: val.to_json, status: :ok )
                else
                    hash = {}
                    hash[:errors] = "Valid parameters: file "
                    render( json: hash.to_json, status: 422 )
                end
            end 
        end
    end
end

I couldn't figure out how to have more than just the value/label parameters for each item so ended up having to just store all components in the label field and then splitting it out :)

@JronZhu
Copy link

JronZhu commented Jul 21, 2016

hi,@rightaway,can you tell me how to add an image to the list item next to the text.I did something with the code like:
data: function (item, input) {
return {label:item.innerHTML=(''+item.label),value:item.value};
}
however,the image url is also used to match suggestion to generate list item,for example,enter 'f'will get all list item because 'f' is in the url---''.
How can I do to solve the bug,THS.
@LeaVerou Can you give me more suggestions?Ths.

@LeaVerou
Copy link
Owner

I think @vlazar is more appropriate to help you here, since he wrote the separate label/value feature.

@vlazar
Copy link
Collaborator

vlazar commented Jul 21, 2016

@JronZhu You'll need to provide custom filter function since the default one matches everything in label. Something similar to filter: in comment above #16888 (comment) where item's label has several values separated with : - "#{i.image_file.wi_thumb.url}:#{i.filename()}:#{i.description}". So in filter it's splitted with text = item.split(":").slice(1).join(":") and Awesomplete.FILTER_CONTAINS function is used for filtering.

However a best way would be to allow arbitrary properties for items. See #16888 (comment)

@JronZhu
Copy link

JronZhu commented Jul 23, 2016

@vlazar Thanks for your helps.I customized data/filter/item function to successfully add images in the dropdown list.data:set label and value property;filter:change the match way;item:change the way to generate the item. It is great!

@qikkeronline
Copy link

@JronZhu would you mind sharing your code here? Looking for the same behaviour :)

@isapir
Copy link

isapir commented Sep 24, 2017

So is this feature implemented or not? The comments suggest that its is implemented, but the issue is still marked as Open.

If it is implemented, I wonder if there is any online example that shows how it works?

@bsgies
Copy link

bsgies commented Jun 20, 2019

@JronZhu Can you tell me how did you add the images next to text dynamically? I'm returning the results via Google Map API.

@saptam-dev
Copy link

saptam-dev commented Apr 6, 2020

Hi
I want to add border left side of the dropdown.
Here:
image

Have any way to add code for border, before/after (
minChars: 1,
autoFirst: true,
maxItems: 10)
this?
Or any other idea?
Please anyone help.
Thanks.

@nickemail
Copy link

my solution works but i can't remove MARK


function hotengine_autocomplete($element) {
    const inputField = document.querySelector($element);
	
	if (!inputField) {
        return; 
    }

    const awesomplete = new Awesomplete(inputField, {
        minChars: 3,
        maxItems: 10,
        autoFirst: false
    });
    
    inputField.addEventListener('input', function () {
        const searchText = hotengine_extractLast(this.value);

        if (searchText.length >= 3) {
            $.ajax({
                url: "/ajax.php?search_shop",
                type: "POST",
                dataType: "json",
                data: {
                    search: searchText,
                    NUM_ONPAGE: 10
                },
                success: function (data) {

                    const suggestions = data.map(item => ({
                        label: hotengine_formatSuggestion(item),
                        value: item.shop_cat_page_title
                    }));

                    awesomplete.list = suggestions;
                    
                }
            });
        }
    });
	
	inputField.addEventListener('awesomplete-selectcomplete', function (event) { 
        const selectedItem = event.text; 

        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = selectedItem.label; 
        const link = tempDiv.querySelector('a'); 

        if (link) {
            window.location.href = link.href; 
        } else {
           inputField.value = selectedItem.value;
        }
    });

    
  
}



function hotengine_formatSuggestion(item) {
    const cleanImagePath = item.shop_cat_page_image.replace(/<\/?mark>/g, '');
    return `
        <div class="autocomplete-item">
            <a class="hotengine-autocomplete-shop-product-read_more" href="${item.url}">
                <span class="hotengine-autocomplete-shop-products-list-img">
                    <img src="${cleanImagePath}" />
                </span>
                <span class="hotengine-autocomplete-shop-product-title">
                    ${item.shop_cat_page_title}
                </span>
                <span class="hotengine-autocomplete-shop-product-price_val">
                    <span class="hotengine-autocomplete-shop-product-price_number">
                        ${item.shop_cat_page_price}
                    </span>
                    ${item.shop_cat_page_price_currency}
                </span>
            </a>
        </div>`;
}



function hotengine_split(val) {
    return val.split(/,\s*/);
}

function hotengine_extractLast(term) {
    return hotengine_split(term).pop();
}


$(function () {
    hotengine_autocomplete("#hotengine-smart_search_input");
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests