from django import forms


class TelephoneInput(forms.TextInput):
    input_type = 'tel'

class KeywordSearch(forms.Form):
    keyword = forms.CharField(required=False, widget=forms.TextInput(attrs={'class':'form-control'}),
        help_text='One or more keywords; can include wildcards * and ?, and exact phrases in quotes.')
    PER_PAGE_OPTIONS = (10, 25, 50, 100)
    page_choices = [(d, d) for d in PER_PAGE_OPTIONS]
    per_page = forms.ChoiceField(label='Results per page',
        choices=page_choices, initial=10)
    SORT_OPTIONS = ('relevance', 'title', 'date (recent)', 'date (oldest)')
    sort_choices = [(d, d) for d in SORT_OPTIONS]
    sort = forms.ChoiceField(label='Sort by',
        choices=sort_choices, initial='relevance')

    title = forms.CharField(required=False,
        help_text='Search by title (keywords or phrase)',
        widget=forms.TextInput(attrs={'placeholder':'Search by title', 'class': 'form-control'}))
    summary = forms.CharField(required=False,
        help_text='Search by summary (keywords or phrase)',
        widget=forms.TextInput(attrs={'placeholder':'Search by summary', 'class': 'form-control'}))
    source = forms.CharField(required=False,
        help_text='Search by source organization or principial investigator (keywords or phrase)',
        widget=forms.TextInput(attrs={'placeholder':'Search by source', 'class': 'form-control'}))
    location = forms.CharField(required=False,
        help_text='Search by geographic location, including nation, country, or economic entity',
        widget=forms.TextInput(attrs={'placeholder':'Search by location', 'class': 'form-control'}))

    # NOTE: could use min_value and max_value here, if we have reasonable values
    # default widget is number input; we can switch to text input if helpful
    # this will nned to be a tel input to allow for devices to display the number pad automatically
    # also would be good to add the class form-control to the <input> element
    start_date = forms.IntegerField(required=False,
        help_text=''''Search by start year of time period covered by data;
        use with end date to specify a range or single year''',
        widget=TelephoneInput(attrs={'class': 'form-control', 'placeholder': 'Start year'}))
    end_date = forms.IntegerField(required=False,
        help_text='Search by end date; use with start date to specify a range or single year',
        widget=TelephoneInput(attrs={'class': 'form-control', 'placeholder': 'End year'}))

    _adv_fields = ['title', 'summary', 'source', 'location']

    search_fields = ['keyword', 'start_date', 'end_date'] + _adv_fields
    # fields that can contain search term; at least one of these is required
    # for validation; all combined generate a list of all search terms

    @property
    def advanced_fields(self):
        'fields that are considered part of the "advanced" search'
        return [self[f] for f in self._adv_fields]

    def clean(self):
        'custom validation to ensure at least one search field is populated'
        cleaned_data = super(KeywordSearch, self).clean()
        # any one search term is sufficient, but at least one is required
        if not any([cleaned_data.get(f, None) for f in self.search_fields]):
            raise forms.ValidationError('You must enter search terms for at least one of %s or %s' % \
                                        (', '.join(self.search_fields[:-1]),
                                         self.search_fields[-1]))
        return cleaned_data

    @property
    def all_search_terms(self):
        'string of all search terms present in any search fields'
        try:
            cleaned_data = self.clean()
            return ' '.join([cleaned_data.get(f) for f in self.search_fields
                             if f in cleaned_data and cleaned_data[f]])
        except:
            # if form is not valid, then there are no search terms
            return ''


@@ -59,16 +59,71 @@
 Input):%0A
+    'HTML5 telephone input (prompt for numeric entry)'%0A
     inpu
@@ -144,29 +144,29 @@
 %0A%0Aclass 
-KeywordSearch
+SearchOptions
 (forms.F
@@ -179,208 +179,74 @@
     
-keyword = forms.CharField(required=False, widget=forms.TextInput(attrs=%7B'class':'form-control'%7D),%0A        help_text='One or more keywords; can include wildcards * and ?, and exact phrases in quotes.')
+# base form with common options for search and browse result pages
 %0A   
@@ -461,64 +461,587 @@
 S = 
-('relevance', 'title', 'date (recent)', 'date (oldest)')
+%5B'title', 'date (recent)', 'date (oldest)'%5D%0A    sort_choices = %5B(d, d) for d in SORT_OPTIONS%5D%0A    sort = forms.ChoiceField(label='Sort by',%0A        choices=sort_choices, initial='title')%0A%0Aclass KeywordSearch(SearchOptions):%0A    keyword = forms.CharField(required=False, widget=forms.TextInput(attrs=%7B'class':'form-control'%7D),%0A        help_text='One or more keywords; can include wildcards * and ?, and exact phrases in quotes.')%0A%0A    # inherit per-page options and input%0A    # extend sort options to include relevance%0A    SORT_OPTIONS = %5B'relevance'%5D + SearchOptions.SORT_OPTIONS
 %0A   

create search options form so pagination and sort logic can be shared by topic/keyword browse and search [#60543676 #66373144]