Table of Contents

ProductPicker

docs

This is a fairly complex application, but it's designed to work with any data source that you want, so I'm including it here.

The nutshell is that this plugin lets users search for data and then select an item and then handle that selection (typically updating the input with the proper value).

The ProductPicker is broken up into three classes:

ProductPicker
Handles the UI and basic functionality of the picker.
Picklet
An instance of a data source that describes what the user can search for and what to do with the data when they search.
FormPickers
Attaches Pickers to each input in a form. If the input has a className that corresponds to a Picklet, that data source becomes an option.

Perhaps an example would be easier to grok. Here I create a ProductPicker that uses the CNET API to retrieve product ids for items available on CNET.com.

new ProductPicker('PickerExample', [CNETProductPicker]);
execute this code

Execute the code, then click inside the input. Search for something like "ipod" and then choose a product. The input will get the appropriate id to reference the item.

Picklets

So ProductPicker handles the UI and whatnot, but in order to be useful we have to be able to describe any data source, configure the input so that the user can search it, handle the data returned by that source, and then interact with the page when the user makes a selection.

Enter Picklets. These classes contain just that information that is unique to a given data source. Each Picklet has a css className associated with it as well as all the functionality described above.

Here's an example Picklet - go ahead an execute this example and add it to the list of available Picklets for the ProductPicker

var CNETProductPicker2 = new Picklet('CNETProductPicker2',{
  url: 'http://api.cnet.com/restApi/v1.0/techProductSearch',
  descriptiveName: 'CNET Product Picker Sortable',
  callBackKey: 'callback', /*see JsonP options*/
  data: {
    partTag: 'mtvo',
    iod: 'hlPrice',
    viewType: 'json',
    sortDesc: 'true'
  }, /*static data*/
  getQuery: function(data){ /*return Ajax or JsonP*/
    return new JsonP(this.options.url, {
      callBackKey: this.options.callBackKey,
      data: $merge(this.options.data, data)
    });
  },
  inputs: {
    query: {
      tagName: 'input',
      type: 'text',
      instructions: 'search for: ',
      tip: 'cnet product search::input a product name and hit <enter> to get results',
      value: '',
      style: {
        width: '100%'
      }
    },
    orderBy: {
      tagName: 'select',
      instructions: 'order by: ',
      style: {
        width: '100%'
      },
      value: ['pop9%2Bdesc', 'edRating7'],
      optionNames: ["most popular", "editor's rating"]
    },
    submit: {
      tagName: 'input',
      type: 'submit',
      style: {
        cssFloat: 'right'
      },
      instructions:'',
      value: 'submit'
    }    
  }, /*form builder*/
  previewHtml: function(data){
    var html = "<div class='dataId' style='color: #999; font-weight:bold; margin: 0px; padding: 0px;'>id: "+data['@id'] +"</div><div class='dataDetails' style='font-size: 10px;'><img height='45' width='"+data.ImageURL[0]['@width']+"' style='margin-left: 10px' src='"+data.ImageURL[1].$+"'/><br /><b>" + data.Name.$ + "</b>";
    if(data.EditorsRating && data.EditorsRating.$) html += "<br/>editors' rating: "+data.EditorsRating.$;
    html += "<div>";
    if(data.LowPrice && data.LowPrice.$) html += "<span class='productPickerPrices'>"+data.LowPrice.$+"</span>";
    if(data.HighPrice && data.HighPrice.$ && (data.LowPrice.$ != data.HighPrice.$))
        html += " to <span class='productPickerPrices'>"+data.HighPrice.$ +"</span>";
    html += "</div></div>";
    html += "<div>";
    if(data.Offers && data.Offers['@numFound'] > 0) 
      html += "resellers: " + data.Offers['@numFound'];
    html += "</div>";
    return html;
  }, /*html template for returned json data*/
  resultsList: function(results){
    if(results.CNETResponse.TechProducts && results.CNETResponse.TechProducts["@numFound"] > 0)
      return results.CNETResponse.TechProducts.TechProduct;
    return false;
  },
  listItemName: function(data){
    return data.Name.$
  }, /*line item name for the selection list*/
  listItemValue: function(data){
    return data['@id'];
  },
  /*handle the click event; user chooses an item, and this function updates the input 
  (or does something else)*/
  updateInput: function(input, data) {
    input.value = data['@id'];
  }  
});
ProductPicker.add(CNETProductPicker2);

Now we have two picklets available on this page: CNETProductPicker and CNETProductPicker2. They are nearly identical, but you'll see what makes them different here:

new ProductPicker('PickerExample2', [CNETProductPicker, CNETProductPicker2]);
execute this code

Execute this block and click the input. You should now see a picker with a select list that lets you choose which data source (the Picklet) you want to use to search.

FormPickers

Now we have numerous Picklets and let's say we want to add ProductPickers to a form with numerous inputs. Here's our html:

<form id="FormPickersExample">
<input type="text" class="CNETProductPicker">
<input type="text" class="CNETProductPicker2">
<input type="text" class="CNETProductPicker CNETProductPicker2">
</form>

Here's that code rendered:



Now our javascript:

new FormPickers('FormPickersExample');
execute this code

As you click into each input, note how they get the appropriate Picklets.

cnet-libraries/09-forms/06-productpicker.txt · Last modified: 2008/11/17 23:25 by aaron-n