'Generate a data list
@param r: the S3Request instance
@param widget: the widget definition as dict
@param attr: controller attributes for the request'

def _datalist(self, r, widget, **attr):

    T = current.T
    widget_get = widget.get
    context = widget_get('context')
    tablename = widget_get('tablename')
    (resource, context) = self._resolve_context(r, tablename, context)
    config = resource.get_config
    list_fields = widget_get('list_fields', config('list_fields', None))
    list_layout = widget_get('list_layout', config('list_layout', None))
    orderby = widget_get('orderby', config('list_orderby', config('orderby', (~ resource.table.created_on))))
    widget_filter = widget_get('filter')
    if widget_filter:
        resource.add_filter(widget_filter)
    list_id = ('profile-list-%s-%s' % (tablename, widget['index']))
    pagesize = widget_get('pagesize', 4)
    representation = r.representation
    if (representation == 'dl'):
        get_vars = r.get_vars
        record_id = get_vars.get('record', None)
        if (record_id is not None):
            resource.add_filter((FS('id') == record_id))
            (start, limit) = (0, 1)
        else:
            start = get_vars.get('start', None)
            limit = get_vars.get('limit', None)
            if (limit is not None):
                try:
                    start = int(start)
                    limit = int(limit)
                except ValueError:
                    (start, limit) = (0, pagesize)
            else:
                start = None
    else:
        (start, limit) = (0, pagesize)
    if ((representation == 'dl') and (r.http in ('DELETE', 'POST'))):
        if ('delete' in r.get_vars):
            return self._dl_ajax_delete(r, resource)
        else:
            r.error(405, current.ERROR.BAD_METHOD)
    (datalist, numrows, ids) = resource.datalist(fields=list_fields, start=start, limit=limit, list_id=list_id, orderby=orderby, layout=list_layout)
    ajaxurl = r.url(vars={'update': widget['index']}, representation='dl')
    data = datalist.html(ajaxurl=ajaxurl, pagesize=pagesize, empty=P(ICON('folder-open-alt'), BR(), self.crud_string(tablename, 'msg_no_match'), _class='empty_card-holder'))
    if (representation == 'dl'):
        current.response.view = 'plain.html'
        return data
    label = widget_get('label', '')
    if label:
        label = T(label)
    icon = widget_get('icon', '')
    if icon:
        icon = ICON(icon)
    if (pagesize and (numrows > pagesize)):
        more = (numrows - pagesize)
        get_vars_new = {}
        if context:
            filters = context.serialize_url(resource)
            for f in filters:
                get_vars_new[f] = filters[f]
        if widget_filter:
            filters = widget_filter.serialize_url(resource)
            for f in filters:
                get_vars_new[f] = filters[f]
        (c, f) = tablename.split('_', 1)
        f = widget_get('function', f)
        url = URL(c=c, f=f, args=['datalist.popup'], vars=get_vars_new)
        more = DIV(A(BUTTON(('%s    (%s)' % (T('see    more'), more)), _class='btn    btn-mini    tiny    button', _type='button'), _class='s3_modal', _href=url, _title=label), _class='more_profile')
    else:
        more = ''
    create_popup = self._create_popup(r, widget, list_id, resource, context, numrows)
    _class = self._lookup_class(r, widget)
    output = DIV(create_popup, H4(icon, label, _class='profile-sub-header'), DIV(data, more, _class='card-holder'), _class=_class)
    return output
