# HG changeset patch # User Katia Saurfelt # Date 1295956256 -3600 # Node ID 1b2fcb9356a384fd7575cfcc762eaa2d860afd25 # Parent 37668bf302f51ad8c6e96b63b42b454f0108cdd8 [widgets, js] add a InOutWidget for multiple select diff -r 37668bf302f5 -r 1b2fcb9356a3 web/data/cubicweb.widgets.js --- a/web/data/cubicweb.widgets.js Tue Jan 25 12:09:59 2011 +0100 +++ b/web/data/cubicweb.widgets.js Tue Jan 25 12:50:56 2011 +0100 @@ -542,3 +542,111 @@ } } }; + + +// InOutWidget This contains specific InOutnWidget javascript +// IE things can not handle hide/show options on select, this cloned list solition (should propably have 2 widgets) + +(function ($) { + var defaultSettings = { + bindDblClick: true + }; + var methods = { + __init__: function(fromSelect, toSelect, options) { + var settings = $.extend({}, defaultSettings, options); + var bindDblClick = settings['bindDblClick']; + var $fromNode = $(cw.jqNode(fromSelect)); + var clonedSelect = $fromNode.clone(); + var $toNode = $(cw.jqNode(toSelect)); + var $addButton = $(this.find('.cwinoutadd')[0]); + var $removeButton = $(this.find('.cwinoutremove')[0]); + // bind buttons + var name = this.attr('id'); + var instanceData = {'fromNode':fromSelect, + 'toNode':toSelect, + 'cloned':clonedSelect, + 'bindDblClick':bindDblClick, + 'name': name}; + $addButton.bind('click', {'instanceData':instanceData}, methods.inOutWidgetAddValues); + $removeButton.bind('click', {'instanceData':instanceData}, methods.inOutWidgetRemoveValues); + if(bindDblClick){ + $toNode.bind('dblclick', {'instanceData': instanceData}, methods.inOutWidgetRemoveValues); + } + methods.inOutWidgetRemplaceSelect($fromNode, $toNode, clonedSelect, bindDblClick, name); + }, + + inOutWidgetRemplaceSelect: function($fromNode, $toNode, clonedSelect, bindDblClick, name){ + var $newSelect = clonedSelect.clone(); + $toNode.find('option').each(function() { + $newSelect.find('$(this)[value='+$(this).val()+']').remove(); + }); + var fromparent = $fromNode.parent(); + if (bindDblClick) { + //XXX jQuery live binding does not seem to work here + $newSelect.bind('dblclick', {'instanceData': {'fromNode':$fromNode.attr('id'), + 'toNode': $toNode.attr('id'), + 'cloned':clonedSelect, + 'bindDblClick':bindDblClick, + 'name': name}}, + methods.inOutWidgetAddValues); + } + $fromNode.remove(); + fromparent.append($newSelect); + }, + + inOutWidgetAddValues: function(event){ + var $fromNode = $(cw.jqNode(event.data.instanceData.fromNode)); + var $toNode = $(cw.jqNode(event.data.instanceData.toNode)); + $fromNode.find('option:selected').each(function() { + var option = $(this); + var newoption = OPTION({'value':option.val()}, + value=option.text()); + $toNode.append(newoption); + var hiddenInput = INPUT({ + type: "hidden", name: event.data.instanceData.name, + value:option.val() + }); + $toNode.parent().append(hiddenInput); + }); + methods.inOutWidgetRemplaceSelect($fromNode, $toNode, event.data.instanceData.cloned, + event.data.instanceData.bindDblClick, + event.data.instanceData.name); + // for ie 7 : ie does not resize correctly the select + if($.browser.msie && $.browser.version.substr(0,1) < 8){ + var p = $toNode.parent(); + var newtoNode = $toNode.clone(); + if (event.data.instanceData.bindDblClick) { + newtoNode.bind('dblclick', {'fromNode': $fromNode.attr('id'), + 'toNode': $toNode.attr('id'), + 'cloned': event.data.instanceData.cloned, + 'bindDblClick': true, + 'name': event.data.instanceData.name}, + methods.inOutWidgetRemoveValues); + } + $toNode.remove(); + p.append(newtoNode); + } + }, + + inOutWidgetRemoveValues: function(event){ + var $fromNode = $(cw.jqNode(event.data.instanceData.toNode)); + var $toNode = $(cw.jqNode(event.data.instanceData.fromNode)); + var name = event.data.instanceData.name.replace(':', '\\:'); + $fromNode.find('option:selected').each(function(){ + var option = $(this); + var newoption = OPTION({'value':option.val()}, + value=option.text()); + option.remove(); + $fromNode.parent().find('input[name]='+ name).each(function() { + $(this).val()==option.val()?$(this).remove():null; + }); + }); + methods.inOutWidgetRemplaceSelect($toNode, $fromNode, event.data.instanceData.cloned, + event.data.instanceData.bindDblClick, + event.data.instanceData.name); + } + }; + $.fn.cwinoutwidget = function(fromSelect, toSelect, options){ + return methods.__init__.apply(this, [fromSelect, toSelect, options]); + }; +})(jQuery); \ No newline at end of file diff -r 37668bf302f5 -r 1b2fcb9356a3 web/formwidgets.py --- a/web/formwidgets.py Tue Jan 25 12:09:59 2011 +0100 +++ b/web/formwidgets.py Tue Jan 25 12:50:56 2011 +0100 @@ -63,6 +63,7 @@ .. autoclass:: cubicweb.web.formwidgets.FCKEditor .. autoclass:: cubicweb.web.formwidgets.AjaxWidget .. autoclass:: cubicweb.web.formwidgets.AutoCompletionWidget +.. autoclass:: cubicweb.web.formwidgets.InOutWidget .. kill or document StaticFileAutoCompletionWidget .. kill or document LazyRestrictedAutoCompletionWidget @@ -999,3 +1000,55 @@ 'label': label, 'imgsrc': imgsrc, 'domid': self.domid, 'href': self.href} +class InOutWidget(Select): + needs_js = ('cubicweb.widgets.js', ) + template = """ + + + + +
%(inoutinput)s
%(addinput)s
%(removeinput)s
%(resinput)s
+""" + add_button = """""" + remove_button ="""""" + + def __init__(self, attrs=None): + super(InOutWidget, self).__init__(attrs, multiple=True) + + def render_select(self, form, field, name, selected=False): + values, attrs = self.values_and_attributes(form, field) + options = [] + inputs = [] + for _option in field.vocabulary(form): + try: + label, value, oattrs = _option + except ValueError: + label, value = _option + if selected: + # add values + if value in values: + options.append(tags.option(label, value=value)) + # add hidden inputs + inputs.append(tags.input(value=value, name=field.dom_id(form), type="hidden")) + else: + options.append(tags.option(label, value=value)) + if 'size' not in attrs: + attrs['size'] = 5 + if 'id' in attrs : + attrs.pop('id') + return tags.select(name=name, multiple=self._multiple, id=name, + options=options, **attrs) + '\n'.join(inputs) + + + def _render(self, form, field, renderer): + domid = field.dom_id(form) + jsnodes = {'widgetid': domid, 'from': 'from_' + domid, 'to': 'to_' + domid} + form._cw.add_onload(u'$(cw.jqNode("%s")).cwinoutwidget("%s", "%s");' + % (jsnodes['widgetid'], jsnodes['from'], jsnodes['to'])) + field.required=True + return self.template % {'widgetid': jsnodes['widgetid'], + 'inoutinput' : self.render_select(form, field, jsnodes['from']), # helpinfo select tag + 'resinput' : self.render_select(form, field, jsnodes['to'], selected=True), # select tag with resultats + 'addinput' : self.add_button % jsnodes, + 'removeinput': self.remove_button % jsnodes + }