'Add-members action: renders a filtered multi-select datatable
form, and creates group_memberships on POST
@param r: the S3Request
@param attr: dictionary of parameters for the method handler
@return: output object to send to the view'

def add_members(self, r, **attr):

    T = current.T
    db = current.db
    s3db = current.s3db
    unaffiliated = ((S3FieldSelector('group_membership.id') == None) & (S3FieldSelector('case.id') != None))
    if (r.http == 'POST'):
        group_id = r.id
        added = 0
        post_vars = r.post_vars
        if all([(name in post_vars) for name in ('add', 'selected', 'mode')]):
            selected = post_vars.selected
            if selected:
                selected = selected.split(',')
            else:
                selected = []
            if (post_vars.mode == 'Exclusive'):
                if ('filterURL' in post_vars):
                    filters = S3URLQuery.parse_url(post_vars.filterURL)
                else:
                    filters = None
                query = (unaffiliated & (~ S3FieldSelector('id').belongs(selected)))
                resource = s3db.resource('pr_person', filter=query, vars=filters)
                rows = resource.select(['id'], as_rows=True)
                selected = [str(row.id) for row in rows]
            gtable = s3db.pr_group_membership
            query = (((gtable.group_id == group_id) & gtable.person_id.belongs(selected)) & (gtable.deleted != True))
            rows = db(query).select(gtable.person_id)
            skip = set((row.person_id for row in rows))
            for record_id in selected:
                try:
                    person_id = int(record_id.strip())
                except ValueError:
                    continue
                if (person_id in skip):
                    continue
                gtable.insert(group_id=group_id, person_id=person_id)
                added += 1
        session = current.session
        if (not selected):
            session.warning = T('No    Persons    Selected!')
        else:
            session.confirmation = (T('%(number)s    Members    added    to    Group') % dict(number=added))
        redirect(r.url(method='', id=group_id, component='group_membership'))
    else:
        resource = s3db.resource('pr_person', vars=r.get_vars)
        resource.add_filter(unaffiliated)
        get_config = resource.get_config
        filter_widgets = get_config('filter_widgets', [])
        filter_widgets.append(S3DateFilter('created_on', label=T('Registered    on')))
        list_fields = ['id', 'first_name', 'last_name', 'gender', 'date_of_birth']
        response = current.response
        get_vars = self.request.get_vars
        if ('displayStart' in get_vars):
            start = int(get_vars['displayStart'])
        else:
            start = None
        if ('pageLength' in get_vars):
            display_length = int(get_vars['pageLength'])
        else:
            display_length = response.s3.ROWSPERPAGE
        limit = (4 * display_length)
        totalrows = resource.count()
        (filter, orderby, left) = resource.datatable_filter(list_fields, get_vars)
        if (not orderby):
            orderby = 'pr_person.created_on    desc'
        resource.add_filter(filter)
        data = resource.select(list_fields, start=start, limit=limit, orderby=orderby, left=left, count=True, represent=True)
        filteredrows = data['numrows']
        dt = S3DataTable(data['rfields'], data['rows'])
        dt_id = 'datatable'
        dt_bulk_actions = [(T('Add    as    Group    Members'), 'add')]
        if (r.representation == 'html'):
            resource.configure(deletable=False)
            open_url = URL(f='person', args=['[id]'])
            S3CRUD.action_buttons(r, deletable=False, read_url=open_url, update_url=open_url)
            response.s3.no_formats = True
            items = dt.html(totalrows, filteredrows, dt_id, dt_ajax_url=URL(c='evr', f='group', args=['add_members'], vars={}, extension='aadata'), dt_bulk_actions=dt_bulk_actions, dt_pageLength=display_length, dt_pagination='true', dt_searching='false')
            resource.configure(deletable=False)
            if filter_widgets:
                _vars = resource.crud._remove_filters(r.get_vars)
                filter_submit_url = r.url(vars=_vars)
                filter_ajax_url = URL(f='person', args=['filter.options'], vars={})
                filter_clear = get_config('filter_clear', True)
                filter_submit = get_config('filter_submit', True)
                filter_form = S3FilterForm(filter_widgets, clear=filter_clear, submit=filter_submit, ajax=True, url=filter_submit_url, ajaxurl=filter_ajax_url, _class='filter-form', _id='datatable-filter-form')
                fresource = s3db.resource(resource.tablename)
                alias = (resource.alias if r.component else None)
                ff = filter_form.html(fresource, r.get_vars, target='datatable', alias=alias)
            else:
                ff = ''
            output = dict(items=items, title=T('Add    Members    to    Group'), addheader=('%s:' % T('Select    People    to    add    them    to    the    Group')), list_filter_form=ff)
            response.view = 'list_filter.html'
            return output
        else:
            if ('draw' in get_vars):
                echo = int(get_vars.draw)
            else:
                echo = None
            items = dt.json(totalrows, filteredrows, dt_id, echo, dt_bulk_actions=dt_bulk_actions)
            response.headers['Content-Type'] = 'application/json'
            return items
