Merge lp:~openerp-dev/openobject-addons/trunk-res-country-state-cleaning-mme into lp:openobject-addons

Proposed by Thibault Delavallée (OpenERP)
Status: Needs review
Proposed branch: lp:~openerp-dev/openobject-addons/trunk-res-country-state-cleaning-mme
Merge into: lp:openobject-addons
Diff against target: 2314 lines (+1439/-426)
30 files modified
account/edi/invoice_action_data.xml (+1/-1)
account/i18n/account.pot (+1/-1)
base_geolocalize/models/res_partner.py (+1/-1)
crm/crm_lead.py (+4/-10)
crm/crm_lead_view.xml (+3/-3)
crm_partner_assign/crm_partner_assign.py (+1/-1)
crm_partner_assign/crm_portal_view.xml (+2/-2)
delivery/delivery.py (+1/-4)
delivery/delivery_view.xml (+2/-2)
edi/models/res_partner.py (+1/-1)
l10n_cn/__openerp__.py (+0/-1)
l10n_cn/base_data.xml (+0/-162)
l10n_cr/l10n_cr_base_data.xml (+0/-40)
l10n_et/__openerp__.py (+0/-1)
l10n_et/data/res.country.state.csv (+0/-12)
l10n_uk/__openerp__.py (+0/-1)
l10n_uk/data/res.country.state.csv (+0/-120)
portal_sale/i18n/portal_sale.pot (+2/-2)
portal_sale/portal_sale_data.xml (+2/-2)
purchase/edi/purchase_order_action_data.xml (+1/-1)
purchase/i18n/purchase.pot (+1/-1)
sale/edi/sale_order_action_data.xml (+1/-1)
sale/i18n/sale.pot (+1/-1)
stock/stock_demo.xml (+0/-1)
website/static/lib/autocomplete/jquery.auto-complete.js (+1369/-0)
website/views/website_templates.xml (+3/-1)
website_quote/data/website_quotation_data.xml (+1/-1)
website_sale/controllers/main.py (+18/-18)
website_sale/static/src/js/website_sale.js (+10/-1)
website_sale/views/website_sale.xml (+13/-33)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/trunk-res-country-state-cleaning-mme
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+208116@code.launchpad.net

Description of the change

[Fix] remove res.country.state model and replace all many2one state by a char field

To post a comment you must log in.
9087. By Niko (OpenERP)

[IMP] Add some video to manisfest ( website, website_blog, website_event, website_ecommerce)

9170. By Mehul Mehta(OpenERP)

[IMP] improvement in code

9171. By Mehul Mehta(OpenERP)

[IMP] improvement in code

Unmerged revisions

9171. By Mehul Mehta(OpenERP)

[IMP] improvement in code

9170. By Mehul Mehta(OpenERP)

[IMP] improvement in code

9169. By Mehul Mehta(OpenERP)

[MERGE] Merged lp:openobject-addons

9168. By Mehul Mehta(OpenERP)

[ADD] autocomplete country selector in website_sale and replace all many2one state by a char field

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'account/edi/invoice_action_data.xml'
2--- account/edi/invoice_action_data.xml 2013-11-27 15:32:57 +0000
3+++ account/edi/invoice_action_data.xml 2014-02-26 06:23:38 +0000
4@@ -79,7 +79,7 @@
5 ${object.company_id.zip} ${object.company_id.city}<br/>
6 % endif
7 % if object.company_id.country_id:
8- ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
9+ ${object.company_id.state}<br/>
10 % endif
11 </span>
12 % if object.company_id.phone:
13
14=== modified file 'account/i18n/account.pot'
15--- account/i18n/account.pot 2013-10-27 12:31:04 +0000
16+++ account/i18n/account.pot 2014-02-26 06:23:38 +0000
17@@ -3262,7 +3262,7 @@
18 " ${object.company_id.zip} ${object.company_id.city}<br/>\n"
19 " % endif\n"
20 " % if object.company_id.country_id:\n"
21-" ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>\n"
22+" ${object.company_id.state}<br/>\n"
23 " % endif\n"
24 " </span>\n"
25 " % if object.company_id.phone:\n"
26
27=== modified file 'base_geolocalize/models/res_partner.py'
28--- base_geolocalize/models/res_partner.py 2013-10-07 14:41:35 +0000
29+++ base_geolocalize/models/res_partner.py 2014-02-26 06:23:38 +0000
30@@ -77,7 +77,7 @@
31 result = geo_find(geo_query_address(street=partner.street,
32 zip=partner.zip,
33 city=partner.city,
34- state=partner.state_id.name,
35+ state=partner.state,
36 country=partner.country_id.name))
37 if result:
38 self.write(cr, uid, [partner.id], {
39
40=== modified file 'crm/crm_lead.py'
41--- crm/crm_lead.py 2014-02-20 16:38:15 +0000
42+++ crm/crm_lead.py 2014-02-26 06:23:38 +0000
43@@ -37,7 +37,7 @@
44 'company_id',
45 'country_id',
46 'section_id',
47- 'state_id',
48+ 'state',
49 'stage_id',
50 'type_id',
51 'user_id',
52@@ -278,7 +278,7 @@
53 'street2': fields.char('Street2', size=128),
54 'zip': fields.char('Zip', change_default=True, size=24),
55 'city': fields.char('City', size=128),
56- 'state_id': fields.many2one("res.country.state", 'State'),
57+ 'state': fields.char('State'),
58 'country_id': fields.many2one('res.country', 'Country'),
59 'phone': fields.char('Phone', size=64),
60 'fax': fields.char('Fax', size=64),
61@@ -324,7 +324,7 @@
62 'street': partner.street,
63 'street2': partner.street2,
64 'city': partner.city,
65- 'state_id': partner.state_id and partner.state_id.id or False,
66+ 'state': partner.state,
67 'country_id': partner.country_id and partner.country_id.id or False,
68 'email_from': partner.email,
69 'phone': partner.phone,
70@@ -736,7 +736,7 @@
71 'zip': lead.zip,
72 'city': lead.city,
73 'country_id': lead.country_id and lead.country_id.id or False,
74- 'state_id': lead.state_id and lead.state_id.id or False,
75+ 'state': lead.state,
76 'is_company': is_company,
77 'type': 'contact'
78 }
79@@ -1060,10 +1060,4 @@
80 message = _("Meeting scheduled at '%s'<br> Subject: %s <br> Duration: %s hour(s)") % (meeting_date, meeting_subject, duration)
81 return self.message_post(cr, uid, ids, body=message, context=context)
82
83- def onchange_state(self, cr, uid, ids, state_id, context=None):
84- if state_id:
85- country_id=self.pool.get('res.country.state').browse(cr, uid, state_id, context).country_id.id
86- return {'value':{'country_id':country_id}}
87- return {}
88-
89 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
90
91=== modified file 'crm/crm_lead_view.xml'
92--- crm/crm_lead_view.xml 2014-02-12 18:08:45 +0000
93+++ crm/crm_lead_view.xml 2014-02-26 06:23:38 +0000
94@@ -119,14 +119,14 @@
95 <field name="partner_id" string="Customer"
96 on_change="on_change_partner_id(partner_id)"
97 options='{"create_name_field": "name"}'
98- context="{'default_name': contact_name, 'default_street': street, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id, 'default_function': function, 'default_phone': phone, 'default_mobile': mobile, 'default_fax': fax, 'default_email': email_from, 'default_user_id': user_id, 'default_section_id': section_id}"/>
99+ context="{'default_name': contact_name, 'default_street': street, 'default_city': city, 'default_state': state, 'default_zip': zip, 'default_country_id': country_id, 'default_function': function, 'default_phone': phone, 'default_mobile': mobile, 'default_fax': fax, 'default_email': email_from, 'default_user_id': user_id, 'default_section_id': section_id}"/>
100 <label for="street" string="Address"/>
101 <div>
102 <field name="street" placeholder="Street..."/>
103 <field name="street2"/>
104 <div class="address_format">
105 <field name="city" placeholder="City" style="width: 40%%"/>
106- <field name="state_id" on_change="onchange_state(state_id)" options='{"no_open": True}' placeholder="State" style="width: 24%%"/>
107+ <field name="state" placeholder="State" style="width: 24%%"/>
108 <field name="zip" placeholder="ZIP" style="width: 34%%"/>
109 </div>
110 <field name="country_id" placeholder="Country" options='{"no_open": True}'/>
111@@ -458,7 +458,7 @@
112 <field name="street2"/>
113 <div class="address_format">
114 <field name="city" placeholder="City" style="width: 40%%"/>
115- <field name="state_id" options='{"no_open": True}' on_change="onchange_state(state_id)" placeholder="State" style="width: 24%%"/>
116+ <field name="state" placeholder="State" style="width: 24%%"/>
117 <field name="zip" placeholder="ZIP" style="width: 34%%"/>
118 </div>
119 <field name="country_id" placeholder="Country" options='{"no_open": True}'/>
120
121=== modified file 'crm_partner_assign/crm_partner_assign.py'
122--- crm_partner_assign/crm_partner_assign.py 2013-12-02 15:09:25 +0000
123+++ crm_partner_assign/crm_partner_assign.py 2014-02-26 06:23:38 +0000
124@@ -148,7 +148,7 @@
125 result = geo_find(geo_query_address(street=lead.street,
126 zip=lead.zip,
127 city=lead.city,
128- state=lead.state_id.name,
129+ state=lead.state,
130 country=lead.country_id.name))
131 if result:
132 self.write(cr, uid, [lead.id], {
133
134=== modified file 'crm_partner_assign/crm_portal_view.xml'
135--- crm_partner_assign/crm_portal_view.xml 2014-02-20 12:38:19 +0000
136+++ crm_partner_assign/crm_portal_view.xml 2014-02-26 06:23:38 +0000
137@@ -53,7 +53,7 @@
138 <field name="zip" readonly="1"/>
139 <field name="city" readonly="1"/>
140 <field name="country_id" readonly="1"/>
141- <field name="state_id" readonly="1"/>
142+ <field name="state" readonly="1"/>
143 </group>
144 <label for="description" colspan="2"/>
145 <field name="description" nolabel="1" colspan="2"/>
146@@ -126,7 +126,7 @@
147 <field name="zip" readonly="1"/>
148 <field name="city" readonly="1"/>
149 <field name="country_id" readonly="1"/>
150- <field name="state_id" readonly="1"/>
151+ <field name="state" readonly="1"/>
152 <field name="phone" readonly="1"/>
153 </group>
154 </group>
155
156=== modified file 'delivery/delivery.py'
157--- delivery/delivery.py 2014-01-30 21:49:44 +0000
158+++ delivery/delivery.py 2014-02-26 06:23:38 +0000
159@@ -86,11 +86,8 @@
160 for grid in carrier.grids_id:
161 get_id = lambda x: x.id
162 country_ids = map(get_id, grid.country_ids)
163- state_ids = map(get_id, grid.state_ids)
164 if country_ids and not contact.country_id.id in country_ids:
165 continue
166- if state_ids and not contact.state_id.id in state_ids:
167- continue
168 if grid.zip_from and (contact.zip or '')< grid.zip_from:
169 continue
170 if grid.zip_to and (contact.zip or '')> grid.zip_to:
171@@ -175,7 +172,7 @@
172 'sequence': fields.integer('Sequence', size=64, required=True, help="Gives the sequence order when displaying a list of delivery grid."),
173 'carrier_id': fields.many2one('delivery.carrier', 'Carrier', required=True, ondelete='cascade'),
174 'country_ids': fields.many2many('res.country', 'delivery_grid_country_rel', 'grid_id', 'country_id', 'Countries'),
175- 'state_ids': fields.many2many('res.country.state', 'delivery_grid_state_rel', 'grid_id', 'state_id', 'States'),
176+ 'state': fields.char('States'),
177 'zip_from': fields.char('Start Zip', size=12),
178 'zip_to': fields.char('To Zip', size=12),
179 'line_ids': fields.one2many('delivery.grid.line', 'grid_id', 'Grid Line'),
180
181=== modified file 'delivery/delivery_view.xml'
182--- delivery/delivery_view.xml 2012-12-21 16:48:08 +0000
183+++ delivery/delivery_view.xml 2014-02-26 06:23:38 +0000
184@@ -70,7 +70,7 @@
185 <group>
186 <group>
187 <field name="country_ids" widget="many2many_tags"/>
188- <field name="state_ids" widget="many2many_tags"/>
189+ <field name="state"/>
190 </group>
191 <group>
192 <label for="zip_from" string="Zip"/>
193@@ -145,7 +145,7 @@
194 <field name="country_ids"/>
195 </group>
196 <group string="States">
197- <field colspan="2" name="state_ids" nolabel="1"/>
198+ <field colspan="2" name="state" nolabel="1"/>
199 <field name="zip_from"/>
200 <field name="zip_to"/>
201 </group>
202
203=== modified file 'edi/models/res_partner.py'
204--- edi/models/res_partner.py 2014-01-23 17:50:54 +0000
205+++ edi/models/res_partner.py 2014-02-26 06:23:38 +0000
206@@ -36,7 +36,7 @@
207 'zip': True,
208 'city': True,
209 'country_id': True,
210- 'state_id': True,
211+ 'state': True,
212 'phone': True,
213 'fax': True,
214 'mobile': True,
215
216=== modified file 'l10n_cn/__openerp__.py'
217--- l10n_cn/__openerp__.py 2012-11-29 22:26:45 +0000
218+++ l10n_cn/__openerp__.py 2014-02-26 06:23:38 +0000
219@@ -35,7 +35,6 @@
220 'data': [
221 'account_chart.xml',
222 'l10n_chart_cn_wizard.xml',
223- 'base_data.xml',
224 ],
225 'license': 'GPL-3',
226 'auto_install': False,
227
228=== removed file 'l10n_cn/base_data.xml'
229--- l10n_cn/base_data.xml 2012-11-29 22:26:45 +0000
230+++ l10n_cn/base_data.xml 1970-01-01 00:00:00 +0000
231@@ -1,162 +0,0 @@
232-<?xml version="1.0"?>
233-<openerp>
234- <data noupdate="1">
235-
236- <!-- 添加省份数据 -->
237- <record id="state_BJ" model="res.country.state">
238- <field name="name">北京市</field>
239- <field name="code">京</field>
240- <field name="country_id" ref="base.cn"/>
241- </record>
242- <record id="state_SH" model="res.country.state">
243- <field name="name">上海市</field>
244- <field name="code">沪</field>
245- <field name="country_id" ref="base.cn"/>
246- </record>
247- <record id="state_ZJ" model="res.country.state">
248- <field name="name">浙江省</field>
249- <field name="code">浙</field>
250- <field name="country_id" ref="base.cn"/>
251- </record>
252- <record id="state_TJ" model="res.country.state">
253- <field name="name">天津市</field>
254- <field name="code">津</field>
255- <field name="country_id" ref="base.cn"/>
256- </record>
257- <record id="state_AH" model="res.country.state">
258- <field name="name">安徽省</field>
259- <field name="code">皖</field>
260- <field name="country_id" ref="base.cn"/>
261- </record>
262- <record id="state_FJ" model="res.country.state">
263- <field name="name">福建省</field>
264- <field name="code">闽</field>
265- <field name="country_id" ref="base.cn"/>
266- </record>
267- <record id="state_CQ" model="res.country.state">
268- <field name="name">重庆市</field>
269- <field name="code">渝 </field>
270- <field name="country_id" ref="base.cn"/>
271- </record>
272- <record id="state_JX" model="res.country.state">
273- <field name="name">江西省</field>
274- <field name="code">赣</field>
275- <field name="country_id" ref="base.cn"/>
276- </record>
277- <record id="state_SD" model="res.country.state">
278- <field name="name">山东省</field>
279- <field name="code">鲁</field>
280- <field name="country_id" ref="base.cn"/>
281- </record>
282- <record id="state_HeN" model="res.country.state">
283- <field name="name">河南省</field>
284- <field name="code">豫</field>
285- <field name="country_id" ref="base.cn"/>
286- </record>
287- <record id="state_NM" model="res.country.state">
288- <field name="name">内蒙古自治区</field>
289- <field name="code">蒙</field>
290- <field name="country_id" ref="base.cn"/>
291- </record>
292- <record id="state_HuB" model="res.country.state">
293- <field name="name">湖北省</field>
294- <field name="code">鄂</field>
295- <field name="country_id" ref="base.cn"/>
296- </record>
297- <record id="state_XJ" model="res.country.state">
298- <field name="name">新疆维吾尔自治区</field>
299- <field name="code">新</field>
300- <field name="country_id" ref="base.cn"/>
301- </record>
302- <record id="state_HuN" model="res.country.state">
303- <field name="name">湖南省</field>
304- <field name="code">湘</field>
305- <field name="country_id" ref="base.cn"/>
306- </record>
307- <record id="state_NX" model="res.country.state">
308- <field name="name">宁夏回族自治区</field>
309- <field name="code">宁</field>
310- <field name="country_id" ref="base.cn"/>
311- </record>
312- <record id="state_GD" model="res.country.state">
313- <field name="name">广东省</field>
314- <field name="code">粤</field>
315- <field name="country_id" ref="base.cn"/>
316- </record>
317- <record id="state_XZ" model="res.country.state">
318- <field name="name">西藏自治区</field>
319- <field name="code">藏</field>
320- <field name="country_id" ref="base.cn"/>
321- </record>
322- <record id="state_HaN" model="res.country.state">
323- <field name="name">海南省</field>
324- <field name="code">琼</field>
325- <field name="country_id" ref="base.cn"/>
326- </record>
327- <record id="state_GX" model="res.country.state">
328- <field name="name">广西壮族自治区</field>
329- <field name="code">桂</field>
330- <field name="country_id" ref="base.cn"/>
331- </record>
332- <record id="state_SC" model="res.country.state">
333- <field name="name">四川省</field>
334- <field name="code">蜀</field>
335- <field name="country_id" ref="base.cn"/>
336- </record>
337- <record id="state_HeB" model="res.country.state">
338- <field name="name">河北省</field>
339- <field name="code">冀</field>
340- <field name="country_id" ref="base.cn"/>
341- </record>
342- <record id="state_GZ" model="res.country.state">
343- <field name="name">贵州省</field>
344- <field name="code">黔</field>
345- <field name="country_id" ref="base.cn"/>
346- </record>
347- <record id="state_SX" model="res.country.state">
348- <field name="name">山西省</field>
349- <field name="code">晋</field>
350- <field name="country_id" ref="base.cn"/>
351- </record>
352- <record id="state_YN" model="res.country.state">
353- <field name="name">云南省</field>
354- <field name="code">滇</field>
355- <field name="country_id" ref="base.cn"/>
356- </record>
357- <record id="state_LN" model="res.country.state">
358- <field name="name">辽宁省</field>
359- <field name="code">辽</field>
360- <field name="country_id" ref="base.cn"/>
361- </record>
362- <record id="state_SX" model="res.country.state">
363- <field name="name">陕西省</field>
364- <field name="code">陕</field>
365- <field name="country_id" ref="base.cn"/>
366- </record>
367- <record id="state_JL" model="res.country.state">
368- <field name="name">吉林省</field>
369- <field name="code">吉</field>
370- <field name="country_id" ref="base.cn"/>
371- </record>
372- <record id="state_GS" model="res.country.state">
373- <field name="name">甘肃省</field>
374- <field name="code">甘</field>
375- <field name="country_id" ref="base.cn"/>
376- </record>
377- <record id="state_HL" model="res.country.state">
378- <field name="name">黑龙江省</field>
379- <field name="code">黑</field>
380- <field name="country_id" ref="base.cn"/>
381- </record>
382- <record id="state_QH" model="res.country.state">
383- <field name="name">青海省</field>
384- <field name="code">青</field>
385- <field name="country_id" ref="base.cn"/>
386- </record>
387- <record id="state_JS" model="res.country.state">
388- <field name="name">江苏省</field>
389- <field name="code">苏</field>
390- <field name="country_id" ref="base.cn"/>
391- </record>
392- </data>
393-</openerp>
394
395=== modified file 'l10n_cr/l10n_cr_base_data.xml'
396--- l10n_cr/l10n_cr_base_data.xml 2013-10-27 12:31:04 +0000
397+++ l10n_cr/l10n_cr_base_data.xml 2014-02-26 06:23:38 +0000
398@@ -1,46 +1,6 @@
399 <openerp>
400 <data>
401
402- <!--
403- Resource: res.country.state
404- Update states
405- -->
406- <record id="state_SJ" model="res.country.state">
407- <field name="code">SJ</field>
408- <field name="name">San Jos&#233;</field>
409- <field name="country_id" ref="base.cr"/>
410- </record>
411- <record id="state_A" model="res.country.state">
412- <field name="code">A</field>
413- <field name="name">Alajuela</field>
414- <field name="country_id" ref="base.cr"/>
415- </record>
416- <record id="state_H" model="res.country.state">
417- <field name="code">H</field>
418- <field name="name">Heredia</field>
419- <field name="country_id" ref="base.cr"/>
420- </record>
421- <record id="state_C" model="res.country.state">
422- <field name="code">C</field>
423- <field name="name">Cartago</field>
424- <field name="country_id" ref="base.cr"/>
425- </record>
426- <record id="state_P" model="res.country.state">
427- <field name="code">P</field>
428- <field name="name">Puntarenas</field>
429- <field name="country_id" ref="base.cr"/>
430- </record>
431- <record id="state_G" model="res.country.state">
432- <field name="code">G</field>
433- <field name="name">Guanacaste</field>
434- <field name="country_id" ref="base.cr"/>
435- </record>
436- <record id="state_L" model="res.country.state">
437- <field name="code">L</field>
438- <field name="name">Lim&#243;n</field>
439- <field name="country_id" ref="base.cr"/>
440- </record>
441- <!--
442 Resource: res.partner.title
443 Update partner titles
444 -->
445
446=== modified file 'l10n_et/__openerp__.py'
447--- l10n_et/__openerp__.py 2013-10-27 12:31:04 +0000
448+++ l10n_et/__openerp__.py 2014-02-26 06:23:38 +0000
449@@ -45,7 +45,6 @@
450 'data/account.tax.code.template.csv',
451 'data/account.chart.template.csv',
452 'data/account.tax.template.csv',
453- 'data/res.country.state.csv',
454 ],
455 'data': [
456 'l10n_et_wizard.xml',
457
458=== removed file 'l10n_et/data/res.country.state.csv'
459--- l10n_et/data/res.country.state.csv 2012-12-14 16:52:54 +0000
460+++ l10n_et/data/res.country.state.csv 1970-01-01 00:00:00 +0000
461@@ -1,12 +0,0 @@
462-"id","country_id:id","code","name"
463-"state_et_1","base.et","AA","Addis Ababa"
464-"state_et_2","base.et","AF","Afar"
465-"state_et_3","base.et","AM","Amhara"
466-"state_et_4","base.et","BN","Benishangul-Gumuz"
467-"state_et_5","base.et","DR","Dire Dawa"
468-"state_et_6","base.et","GM","Gambella Peoples"
469-"state_et_7","base.et","HR","Harrari Peoples"
470-"state_et_8","base.et","OR","Oromia"
471-"state_et_9","base.et","SM","Somalia"
472-"state_et_10","base.et","SP","Southern Peoples, Nations, and Nationalities"
473-"state_et_11","base.et","TG","Tigray"
474
475=== modified file 'l10n_uk/__openerp__.py'
476--- l10n_uk/__openerp__.py 2012-12-06 15:38:56 +0000
477+++ l10n_uk/__openerp__.py 2014-02-26 06:23:38 +0000
478@@ -39,7 +39,6 @@
479 'data/account.tax.code.template.csv',
480 'data/account.chart.template.csv',
481 'data/account.tax.template.csv',
482- 'data/res.country.state.csv',
483 'l10n_uk_wizard.xml',
484 ],
485 'demo' : ['demo/demo.xml'],
486
487=== removed file 'l10n_uk/data/res.country.state.csv'
488--- l10n_uk/data/res.country.state.csv 2011-09-16 14:01:34 +0000
489+++ l10n_uk/data/res.country.state.csv 1970-01-01 00:00:00 +0000
490@@ -1,120 +0,0 @@
491-"id","country_id:id","code","name"
492-"state_uk_1","base.uk","A1","Aberdeenshire"
493-"state_uk_2","base.uk","A5","Angus"
494-"state_uk_3","base.uk","A7","Argyll"
495-"state_uk_4","base.uk","A9","Avon"
496-"state_uk_5","base.uk","B1","Ayrshire"
497-"state_uk_6","base.uk","B3","Banffshire"
498-"state_uk_7","base.uk","B5","Bedfordshire"
499-"state_uk_8","base.uk","B7","Berkshire"
500-"state_uk_9","base.uk","B9","Berwickshire"
501-"state_uk_10","base.uk","C1","Buckinghamshire"
502-"state_uk_11","base.uk","C3","Caithness"
503-"state_uk_12","base.uk","C5","Cambridgeshire"
504-"state_uk_13","base.uk","C6","Channel Islands"
505-"state_uk_14","base.uk","C7","Cheshire"
506-"state_uk_15","base.uk","C9","Clackmannanshire"
507-"state_uk_16","base.uk","D1","Cleveland"
508-"state_uk_17","base.uk","D3","Clwyd"
509-"state_uk_18","base.uk","D5","County Antrim"
510-"state_uk_19","base.uk","D7","County Armagh"
511-"state_uk_20","base.uk","D9","County Down"
512-"state_uk_21","base.uk","E1","County Durham"
513-"state_uk_22","base.uk","E3","County Fermanagh"
514-"state_uk_23","base.uk","E5","County Londonderry"
515-"state_uk_24","base.uk","E7","County Tyrone"
516-"state_uk_25","base.uk","E9","Cornwall"
517-"state_uk_26","base.uk","F1","Cumbria"
518-"state_uk_27","base.uk","F3","Derbyshire"
519-"state_uk_28","base.uk","F5","Devon"
520-"state_uk_29","base.uk","F7","Dorset"
521-"state_uk_30","base.uk","F9","Dumfriesshire"
522-"state_uk_31","base.uk","G1","Dunbartonshire"
523-"state_uk_32","base.uk","G3","Dyfed"
524-"state_uk_33","base.uk","G5","East Lothian"
525-"state_uk_34","base.uk","G7","East Sussex"
526-"state_uk_35","base.uk","G9","Essex"
527-"state_uk_36","base.uk","H1","Fife"
528-"state_uk_37","base.uk","H3","Gloucestershire"
529-"state_uk_38","base.uk","H7","Gwent"
530-"state_uk_39","base.uk","H9","Gwynedd"
531-"state_uk_40","base.uk","I1","Hampshire"
532-"state_uk_41","base.uk","I3","Herefordshire"
533-"state_uk_42","base.uk","I5","Hertfordshire"
534-"state_uk_43","base.uk","I7","Inverness-Shire"
535-"state_uk_44","base.uk","I9","Isle of Arran"
536-"state_uk_45","base.uk","J1","Isle of Barra"
537-"state_uk_46","base.uk","J3","Isle of Benbecula"
538-"state_uk_47","base.uk","J5","Isle of Bute"
539-"state_uk_48","base.uk","J7","Isle of Canna"
540-"state_uk_49","base.uk","J9","Isle of Coll"
541-"state_uk_50","base.uk","K1","Isle of Colonsay"
542-"state_uk_51","base.uk","K3","Isle of Cumbrae"
543-"state_uk_52","base.uk","K5","Isle of Eigg"
544-"state_uk_53","base.uk","K7","Isle of Gigha"
545-"state_uk_54","base.uk","K9","Isle of Harris"
546-"state_uk_55","base.uk","L1","Isle of Iona"
547-"state_uk_56","base.uk","L2","Isle of Islay"
548-"state_uk_57","base.uk","L5","Isle of Jura"
549-"state_uk_58","base.uk","L7","Isle of Lewis"
550-"state_uk_59","base.uk","L9","Isle of Man"
551-"state_uk_60","base.uk","M1","Isle of Mull"
552-"state_uk_61","base.uk","M3","Isle of North Uist"
553-"state_uk_62","base.uk","M7","Isle of Rhum"
554-"state_uk_63","base.uk","M9","Isle of Scalpay"
555-"state_uk_64","base.uk","N1","Shetland Islands"
556-"state_uk_65","base.uk","N3","Isle of Skye"
557-"state_uk_66","base.uk","N5","Isle of South Uist"
558-"state_uk_67","base.uk","N7","Isle of Tiree"
559-"state_uk_68","base.uk","N9","Isle of Wight"
560-"state_uk_69","base.uk","O5","Kent"
561-"state_uk_70","base.uk","O7","Kincardineshire"
562-"state_uk_71","base.uk","O9","Kinross-Shire"
563-"state_uk_72","base.uk","P1","Kirkcudbrightshire"
564-"state_uk_73","base.uk","P5","Lancashire"
565-"state_uk_74","base.uk","P7","Leicestershire"
566-"state_uk_75","base.uk","P9","Lincolnshire"
567-"state_uk_76","base.uk","Q3","Merseyside"
568-"state_uk_77","base.uk","Q5","Mid Glamorgan"
569-"state_uk_78","base.uk","Q9","Middlesex"
570-"state_uk_79","base.uk","R1","Morayshire"
571-"state_uk_80","base.uk","R3","Nairnshire"
572-"state_uk_81","base.uk","R7","North Humberside"
573-"state_uk_82","base.uk","R9","North Yorkshire"
574-"state_uk_83","base.uk","S1","Northamptonshire"
575-"state_uk_84","base.uk","S3","Northumberland"
576-"state_uk_85","base.uk","S5","Nottinghamshire"
577-"state_uk_86","base.uk","S7","Oxfordshire"
578-"state_uk_87","base.uk","S9","Peeblesshire"
579-"state_uk_88","base.uk","T1","Perthshire"
580-"state_uk_89","base.uk","T3","Powys"
581-"state_uk_90","base.uk","T5","Renfrewshire"
582-"state_uk_91","base.uk","T7","Ross-Shire"
583-"state_uk_92","base.uk","T9","Roxburghshire"
584-"state_uk_93","base.uk","U3","Selkirkshire"
585-"state_uk_94","base.uk","U5","Shropshire"
586-"state_uk_95","base.uk","U7","Somerset"
587-"state_uk_96","base.uk","U9","South Glamorgan"
588-"state_uk_97","base.uk","V1","South Humberside"
589-"state_uk_98","base.uk","V3","South Yorkshire"
590-"state_uk_99","base.uk","V5","Staffordshire"
591-"state_uk_100","base.uk","V7","Stirlingshire"
592-"state_uk_101","base.uk","V9","Suffolk"
593-"state_uk_102","base.uk","W1","Surrey"
594-"state_uk_103","base.uk","W3","Sutherland"
595-"state_uk_104","base.uk","W5","Tyne and Wear"
596-"state_uk_105","base.uk","W7","Warwickshire"
597-"state_uk_106","base.uk","W9","West Glamorgan"
598-"state_uk_107","base.uk","X1","West Lothian"
599-"state_uk_108","base.uk","X3","West Midlands"
600-"state_uk_109","base.uk","X5","West Sussex"
601-"state_uk_110","base.uk","X7","West Yorkshire"
602-"state_uk_111","base.uk","X9","Wigtownshire"
603-"state_uk_112","base.uk","Y1","Wiltshire"
604-"state_uk_113","base.uk","Y3","Worcestershire"
605-"state_uk_114","base.uk","M5","Orkney"
606-"state_uk_115","base.uk","O1","Isles of Scilly"
607-"state_uk_116","base.uk","P3","Lanarkshire"
608-"state_uk_117","base.uk","Q1","London"
609-"state_uk_118","base.uk","Q7","Midlothian"
610-"state_uk_119","base.uk","R5","Norfolk"
611
612=== modified file 'portal_sale/i18n/portal_sale.pot'
613--- portal_sale/i18n/portal_sale.pot 2013-10-27 12:31:04 +0000
614+++ portal_sale/i18n/portal_sale.pot 2014-02-26 06:23:38 +0000
615@@ -125,7 +125,7 @@
616 " ${object.company_id.zip} ${object.company_id.city}<br/>\n"
617 " % endif\n"
618 " % if object.company_id.country_id:\n"
619-" ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>\n"
620+" ${object.company_id.state}<br/>\n"
621 " % endif\n"
622 " </span>\n"
623 " % if object.company_id.phone:\n"
624@@ -252,7 +252,7 @@
625 " ${object.company_id.zip} ${object.company_id.city}<br/>\n"
626 " % endif\n"
627 " % if object.company_id.country_id:\n"
628-" ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>\n"
629+" ${object.company_id.state}<br/>\n"
630 " % endif\n"
631 " </span>\n"
632 " % if object.company_id.phone:\n"
633
634=== modified file 'portal_sale/portal_sale_data.xml'
635--- portal_sale/portal_sale_data.xml 2013-12-04 13:00:23 +0000
636+++ portal_sale/portal_sale_data.xml 2014-02-26 06:23:38 +0000
637@@ -75,7 +75,7 @@
638 ${object.company_id.zip} ${object.company_id.city}<br/>
639 % endif
640 % if object.company_id.country_id:
641- ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
642+ ${object.company_id.state}<br/>
643 % endif
644 </span>
645 % if object.company_id.phone:
646@@ -162,7 +162,7 @@
647 ${object.company_id.zip} ${object.company_id.city}<br/>
648 % endif
649 % if object.company_id.country_id:
650- ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
651+ ${object.company_id.state}<br/>
652 % endif
653 </span>
654 % if object.company_id.phone:
655
656=== modified file 'purchase/edi/purchase_order_action_data.xml'
657--- purchase/edi/purchase_order_action_data.xml 2013-11-27 15:32:57 +0000
658+++ purchase/edi/purchase_order_action_data.xml 2014-02-26 06:23:38 +0000
659@@ -71,7 +71,7 @@
660 ${object.company_id.zip} ${object.company_id.city}<br/>
661 % endif
662 % if object.company_id.country_id:
663- ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
664+ ${object.company_id.state}<br/>
665 % endif
666 </span>
667 % if object.company_id.phone:
668
669=== modified file 'purchase/i18n/purchase.pot'
670--- purchase/i18n/purchase.pot 2013-10-27 12:31:04 +0000
671+++ purchase/i18n/purchase.pot 2014-02-26 06:23:38 +0000
672@@ -938,7 +938,7 @@
673 " ${object.company_id.zip} ${object.company_id.city}<br/>\n"
674 " % endif\n"
675 " % if object.company_id.country_id:\n"
676-" ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>\n"
677+" ${object.company_id.state}<br/>\n"
678 " % endif\n"
679 " </span>\n"
680 " % if object.company_id.phone:\n"
681
682=== modified file 'sale/edi/sale_order_action_data.xml'
683--- sale/edi/sale_order_action_data.xml 2013-11-27 15:32:57 +0000
684+++ sale/edi/sale_order_action_data.xml 2014-02-26 06:23:38 +0000
685@@ -80,7 +80,7 @@
686 ${object.company_id.zip} ${object.company_id.city}<br/>
687 % endif
688 % if object.company_id.country_id:
689- ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
690+ ${object.company_id.state}<br/>
691 % endif
692 </span>
693 % if object.company_id.phone:
694
695=== modified file 'sale/i18n/sale.pot'
696--- sale/i18n/sale.pot 2013-10-27 12:31:04 +0000
697+++ sale/i18n/sale.pot 2014-02-26 06:23:38 +0000
698@@ -1604,7 +1604,7 @@
699 " ${object.company_id.zip} ${object.company_id.city}<br/>\n"
700 " % endif\n"
701 " % if object.company_id.country_id:\n"
702-" ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>\n"
703+" ${object.company_id.state}<br/>\n"
704 " % endif\n"
705 " </span>\n"
706 " % if object.company_id.phone:\n"
707
708=== modified file 'stock/stock_demo.xml'
709--- stock/stock_demo.xml 2013-12-02 15:09:25 +0000
710+++ stock/stock_demo.xml 2014-02-26 06:23:38 +0000
711@@ -187,7 +187,6 @@
712 <field eval="1" name="active"/>
713 <field name="street">90 Streets Avenue</field>
714 <field model="res.country" name="country_id" search="[('code','ilike','us')]"/>
715- <field model="res.country.state" name="state_id" search="[('code','ilike','il')]"/>
716 <field name="zip">60610</field>
717 <field name="city">Chicago</field>
718 <field name="email">chicago@yourcompany.com</field>
719
720=== added directory 'website/static/lib/autocomplete'
721=== added file 'website/static/lib/autocomplete/jquery.auto-complete.js'
722--- website/static/lib/autocomplete/jquery.auto-complete.js 1970-01-01 00:00:00 +0000
723+++ website/static/lib/autocomplete/jquery.auto-complete.js 2014-02-26 06:23:38 +0000
724@@ -0,0 +1,1369 @@
725+/*!
726+ * Auto Complete 5.1
727+ * April 13, 2010
728+ * Corey Hart @ http://www.codenothing.com
729+ */
730+(function( $, window, undefined ) {
731+
732+ // Expose autoComplete to the jQuery chain
733+ $.fn.autoComplete = function() {
734+ // Force array of arguments
735+ var args = Slice.call( arguments ),
736+ self = this,
737+ first = args.shift(),
738+ isMethod = typeof first === 'string',
739+ handler, el;
740+
741+ // Deep namespacing is not supported in jQuery, a mistake I made in v4.1
742+ if ( isMethod ) {
743+ first = first.replace( rdot, '-' );
744+ }
745+
746+ // Allow for passing array of arguments, or multiple arguments
747+ // Eg: .autoComplete('trigger', [arg1, arg2, arg3...]) or .autoComplete('trigger', arg1, arg2, arg3...)
748+ // Mainly to allow for .autoComplete('trigger', arguments) to work
749+ // Note*: Some triggers pass an array as the first param, so check against that first
750+ args = ( AutoComplete.arrayMethods[ first ] === TRUE && $.isArray( args[0] ) && $.isArray( args[0][0] ) ) ||
751+ ( args.length === 1 && $.isArray( args[0] ) ) ?
752+ args[0] : args;
753+
754+ // Check method against handlers that need to use triggerHandler
755+ handler = isMethod && ( AutoComplete.handlerMethods[ first ] === -1 || args.length < ( AutoComplete.handlerMethods[ first ] || 0 ) ) ?
756+ 'triggerHandler' : 'trigger';
757+
758+ return isMethod ?
759+ self[ handler ]( 'autoComplete.' + first, args ) :
760+
761+ // Allow passing a jquery event special object {from $.Event()}
762+ first && first.preventDefault !== undefined ? self.trigger( first, args ) :
763+
764+ // Initiate the autocomplete on each element (Only takes a single argument, the options object)
765+ self.each(function(){
766+ if ( $( el = this ).data( 'autoComplete' ) !== TRUE ) {
767+ AutoCompleteFunction( el, first );
768+ }
769+ });
770+ };
771+
772+ // bgiframe is needed to fix z-index problem for IE6 users.
773+ $.fn.bgiframe = $.fn.bgiframe ? $.fn.bgiframe : $.fn.bgIframe ? $.fn.bgIframe : function() {
774+ // For applications that don't have bgiframe plugin installed, create a useless
775+ // function that doesn't break the chain
776+ return this;
777+ };
778+
779+ // Allows for single event binding to document and forms associated with the autoComplete inputs
780+ // by deferring the event to the input in focus
781+ function setup( $input, inputIndex ) {
782+ if ( setup.flag !== TRUE ) {
783+ setup.flag = TRUE;
784+ rootjQuery.bind( 'click.autoComplete', function( event ) {
785+ AutoComplete.getFocus( TRUE ).trigger( 'autoComplete.document-click', [ event ] );
786+ });
787+ }
788+
789+ var $form = $input.closest( 'form' ), formList = $form.data( 'ac-inputs' ) || {}, $el;
790+
791+ formList[ inputIndex ] = TRUE;
792+ $form.data( 'ac-inputs', formList );
793+
794+ if ( $form.data( 'autoComplete' ) !== TRUE ) {
795+ $form.data( 'autoComplete', TRUE ).bind( 'submit.autoComplete', function( event ) {
796+ return ( $el = AutoComplete.getFocus( TRUE ) ).length ?
797+ $el.triggerHandler( 'autoComplete.form-submit', [ event, this ] ) :
798+ TRUE;
799+ });
800+ }
801+ }
802+
803+ // Removes the single events attached to the document and respective input form
804+ function teardown( $input, inputIndex ) {
805+ AutoComplete.remove( inputIndex );
806+
807+ if ( setup.flag === TRUE && AutoComplete.length === 0 ) {
808+ setup.flag = FALSE;
809+ rootjQuery.unbind( 'click.autoComplete' );
810+ }
811+
812+ var $form = $input.closest( 'form' ), formList = $form.data( 'ac-inputs' ) || {}, i;
813+
814+ formList[ inputIndex ] = FALSE;
815+ for ( i in formList ) {
816+ if ( formList.hasOwnProperty( i ) && formList[ i ] === TRUE ) {
817+ return;
818+ }
819+ }
820+
821+ $form.unbind( 'submit.autoComplete' );
822+ }
823+
824+ // Default function for adding all supply items to the list
825+ function allSupply( event, ui ) {
826+ if ( ! $.isArray( ui.supply ) ) {
827+ return [];
828+ }
829+
830+ for ( var i = -1, l = ui.supply.length, ret = [], entry; ++i < l; ) {
831+ entry = ui.supply[ i ];
832+ entry = entry && entry.value ? entry : { value: entry };
833+ ret.push( entry );
834+ }
835+
836+ return ret;
837+ }
838+
839+
840+
841+// Internals
842+var
843+ // Munging
844+ TRUE = true,
845+ FALSE = false,
846+
847+ // Copy of the slice prototype
848+ Slice = Array.prototype.slice,
849+
850+ // Make a copy of the document element for caching
851+ rootjQuery = $( window.document ),
852+
853+ // Also make a copy of an empty jQuery set for fast referencing
854+ emptyjQuery = $( ),
855+
856+ // regex's
857+ rdot = /\./,
858+
859+ // Opera and Firefox on Mac need to use the keypress event to track holding of
860+ // a key down and not releasing
861+ keypress = window.opera || ( /macintosh/i.test( window.navigator.userAgent ) && $.browser.mozilla ),
862+
863+ // Event flag that gets passed around
864+ ExpandoFlag = 'autoComplete_' + $.expando,
865+
866+ // Make a local copy of the key codes used throughout the plugin
867+ KEY = {
868+ backspace: 8,
869+ tab: 9,
870+ enter: 13,
871+ shift: 16,
872+ space: 32,
873+ pageup: 33,
874+ pagedown: 34,
875+ left: 37,
876+ up: 38,
877+ right: 39,
878+ down: 40
879+ },
880+
881+ // Attach global aspects to jQuery itself
882+ AutoComplete = $.autoComplete = {
883+ // Autocomplete Version
884+ version: '5.1',
885+
886+ // Index Counter
887+ counter: 0,
888+
889+ // Length of stack
890+ length: 0,
891+
892+ // Storage of elements
893+ stack: {},
894+
895+ // jQuery object versions of the storage elements
896+ jqStack: {},
897+
898+ // Storage order of uid's
899+ order: [],
900+
901+ // Global access to elements in use
902+ hasFocus: FALSE,
903+
904+ // Expose the used keycodes
905+ keys: KEY,
906+
907+ // Methods whose first argument may contain an array
908+ arrayMethods: {
909+ 'button-supply': TRUE,
910+ 'direct-supply': TRUE
911+ },
912+
913+ // Defines the maximum number of arguments that can be passed for using
914+ // triggerHandler method instead of trigger. Passing -1 forces triggerHandler
915+ // no matter the number of arguments
916+ handlerMethods: {
917+ 'option': 2
918+ },
919+
920+ // Events triggered whenever one of the autoComplete
921+ // input's come into focus or blur out.
922+ focus: undefined,
923+ blur: undefined,
924+
925+ // Allow access to jquery cached object versions of the elements
926+ getFocus: function( jqStack ) {
927+ return ! AutoComplete.order[0] ? jqStack ? emptyjQuery : undefined :
928+ jqStack ? AutoComplete.jqStack[ AutoComplete.order[0] ] :
929+ AutoComplete.stack[ AutoComplete.order[0] ];
930+ },
931+
932+ getPrevious: function( jqStack ) {
933+ // Removing elements cause some indexs on the order stack
934+ // to become undefined, so loop until one is found
935+ for ( var i = 0, l = AutoComplete.order.length; ++i < l; ) {
936+ if ( AutoComplete.order[i] ) {
937+ return jqStack ?
938+ AutoComplete.jqStack[ AutoComplete.order[i] ] :
939+ AutoComplete.stack[ AutoComplete.order[i] ];
940+ }
941+ }
942+
943+ return jqStack ? emptyjQuery : undefined;
944+ },
945+
946+ remove: function( n ) {
947+ for ( var i = -1, l = AutoComplete.order.length; ++i < l; ) {
948+ if ( AutoComplete.order[i] === n ) {
949+ AutoComplete.order[i] = undefined;
950+ }
951+ }
952+
953+ AutoComplete.length--;
954+ delete AutoComplete.stack[n];
955+ },
956+
957+ // Returns full stack in jQuery form
958+ getAll: function(){
959+ for ( var i = -1, l = AutoComplete.counter, stack = []; ++i < l; ) {
960+ if ( AutoComplete.stack[i] ) {
961+ stack.push( AutoComplete.stack[i] );
962+ }
963+ }
964+ return $( stack );
965+ },
966+
967+ defaults: {
968+ // To smooth upgrade process to 5.x, set backwardsCompatible to true
969+ backwardsCompatible: FALSE,
970+ // Server Script Path
971+ ajax: 'ajax.php',
972+ ajaxCache: $.ajaxSettings.cache,
973+ // Data Configuration
974+ dataSupply: [],
975+ dataFn: undefined,
976+ formatSupply: undefined,
977+ // Drop List CSS
978+ list: 'auto-complete-list',
979+ rollover: 'auto-complete-list-rollover',
980+ width: undefined, // Defined as inputs width when extended (can be overridden with this global/options/meta)
981+ striped: undefined,
982+ maxHeight: undefined,
983+ bgiframe: undefined,
984+ newList: FALSE,
985+ // Post Data
986+ postVar: 'value',
987+ postData: {},
988+ postFormat: undefined,
989+ // Limitations
990+ minChars: 1,
991+ maxItems: -1,
992+ maxRequests: 0,
993+ maxRequestsDeep: FALSE,
994+ requestType: 'POST',
995+ // Input
996+ inputControl: undefined,
997+ autoFill: FALSE,
998+ nonInput: [ KEY.shift, KEY.left, KEY.right ],
999+ multiple: FALSE,
1000+ multipleSeparator: ' ',
1001+ // Events
1002+ onBlur: undefined,
1003+ onFocus: undefined,
1004+ onHide: undefined,
1005+ onLoad: undefined,
1006+ onMaxRequest: undefined,
1007+ onRollover: undefined,
1008+ onSelect: undefined,
1009+ onShow: undefined,
1010+ onListFormat: undefined,
1011+ onSubmit: undefined,
1012+ spinner: undefined,
1013+ preventEnterSubmit: TRUE,
1014+ delay: 0,
1015+ // Caching Options
1016+ useCache: TRUE,
1017+ cacheLimit: 50
1018+ }
1019+ },
1020+
1021+ // Autocomplete function
1022+ AutoCompleteFunction = function( self, options ) {
1023+ // Start with counters as they are used within declarations
1024+ AutoComplete.length++;
1025+ AutoComplete.counter++;
1026+
1027+ // Input specific vars
1028+ var $input = $( self ).attr( 'autocomplete', 'off' ),
1029+ // Data object stored on 'autoComplete' data namespace of input
1030+ ACData = {},
1031+ // Track every event triggered
1032+ LastEvent = {},
1033+ // String of current input value
1034+ inputval = '',
1035+ // Holds the current list
1036+ currentList = [],
1037+ // Place holder for all list elements
1038+ $elems = { length: 0 },
1039+ // Place holder for the list element in focus
1040+ $li,
1041+ // View and heights for scrolling
1042+ view, ulHeight, liHeight, liPerView,
1043+ // Hardcoded value for ul visiblity
1044+ ulOpen = FALSE,
1045+ // Timer for delay
1046+ timeid,
1047+ // Ajax requests holder
1048+ xhr,
1049+ // li element in focus, and its data
1050+ liFocus = -1, liData,
1051+ // Fast referencing for multiple selections
1052+ separator,
1053+ // Index of current input
1054+ inputIndex = AutoComplete.counter,
1055+ // Number of requests made
1056+ requests = 0,
1057+ // Internal Per Input Cache
1058+ cache = {
1059+ length: 0,
1060+ val: undefined,
1061+ list: {}
1062+ },
1063+
1064+ // Merge defaults with passed options and metadata options
1065+ settings = $.extend(
1066+ { width: $input.outerWidth() },
1067+ AutoComplete.defaults,
1068+ options||{},
1069+ $.metadata ? $input.metadata() : {}
1070+ ),
1071+
1072+ // Create the drop list (Use an existing one if possible)
1073+ $ul = ! settings.newList && rootjQuery.find( 'ul.' + settings.list )[ 0 ] ?
1074+ rootjQuery.find( 'ul.' + settings.list ).eq( 0 ).bgiframe( settings.bgiframe ) :
1075+ $('<ul/>').appendTo('body').addClass( settings.list ).bgiframe( settings.bgiframe ).hide().data( 'ac-selfmade', TRUE );
1076+
1077+
1078+ // Start Binding
1079+ $input.data( 'autoComplete', ACData = {
1080+ index: inputIndex,
1081+ hasFocus: FALSE,
1082+ active: TRUE,
1083+ settings: settings,
1084+ initialSettings: $.extend( TRUE, {}, settings )
1085+ });
1086+
1087+ // IE catches the enter key only on keypress/keyup, so add a helper
1088+ // to track that event if needed
1089+ if ( $.browser.msie ) {
1090+ $input.bind( 'keypress.autoComplete', function( event ) {
1091+ if ( ! ACData.active ) {
1092+ return TRUE;
1093+ }
1094+
1095+ if ( event.keyCode === KEY.enter ) {
1096+ var enter = TRUE;
1097+
1098+ // See entertracking on main key(press/down) event for explanation
1099+ if ( $li && $li.hasClass( settings.rollover ) ) {
1100+ enter = settings.preventEnterSubmit && ulOpen ? FALSE : TRUE;
1101+ select( event );
1102+ }
1103+ else if ( ulOpen ) {
1104+ $ul.hide( event );
1105+ }
1106+
1107+ return enter;
1108+ }
1109+ });
1110+ }
1111+
1112+
1113+ // Opera && firefox on Mac use keypress to track holding down of key,
1114+ // while everybody else uses keydown for same functionality
1115+ $input.bind( keypress ? 'keypress.autoComplete' : 'keydown.autoComplete' , function( event ) {
1116+ // If autoComplete has been disabled, prevent input events
1117+ if ( ! ACData.active ) {
1118+ return TRUE;
1119+ }
1120+
1121+ // Track last event and store code for munging
1122+ var key = ( LastEvent = event ).keyCode, enter = FALSE;
1123+
1124+
1125+ // Tab Key
1126+ if ( key === KEY.tab && ulOpen ) {
1127+ select( event );
1128+ }
1129+ // Enter Key
1130+ else if ( key === KEY.enter ) {
1131+ // When tracking whether to submit the form or not, we have
1132+ // to ensure that the user is actually selecting an element from the drop
1133+ // down list. It no element is selected, then hide the list and track form
1134+ // submission. If an element is selected, then track for submission first,
1135+ // then hide the list.
1136+ enter = TRUE;
1137+ if ( $li && $li.hasClass( settings.rollover ) ) {
1138+ enter = settings.preventEnterSubmit && ulOpen ? FALSE : TRUE;
1139+ select( event );
1140+ }
1141+ else if ( ulOpen ) {
1142+ $ul.hide( event );
1143+ }
1144+ }
1145+ // Up Arrow
1146+ else if ( key === KEY.up && ulOpen ) {
1147+ if ( liFocus > 0 ) {
1148+ liFocus--;
1149+ up( event );
1150+ } else {
1151+ liFocus = -1;
1152+ $input.val( inputval );
1153+ $ul.hide( event );
1154+ }
1155+ }
1156+ // Down Arrow
1157+ else if ( key === KEY.down && ulOpen ) {
1158+ if ( liFocus < $elems.length - 1 ) {
1159+ liFocus++;
1160+ down( event );
1161+ }
1162+ }
1163+ // Page Up
1164+ else if ( key === KEY.pageup && ulOpen ) {
1165+ if ( liFocus > 0 ) {
1166+ liFocus -= liPerView;
1167+
1168+ if ( liFocus < 0 ) {
1169+ liFocus = 0;
1170+ }
1171+
1172+ up( event );
1173+ }
1174+ }
1175+ // Page Down
1176+ else if ( key === KEY.pagedown && ulOpen ) {
1177+ if ( liFocus < $elems.length - 1 ) {
1178+ liFocus += liPerView;
1179+
1180+ if ( liFocus > $elems.length - 1 ) {
1181+ liFocus = $elems.length - 1;
1182+ }
1183+
1184+ down( event );
1185+ }
1186+ }
1187+ // Check for non input values defined by user
1188+ else if ( settings.nonInput && $.inArray( key, settings.nonInput ) > -1 ) {
1189+ $ul.html('').hide( event );
1190+ enter = TRUE;
1191+ }
1192+ // Everything else is considered possible input, so
1193+ // return before keyup prevention flag is set
1194+ else {
1195+ return TRUE;
1196+ }
1197+
1198+ // Prevent autoComplete keyup event's from triggering by
1199+ // attaching a flag to the last event
1200+ LastEvent[ 'keydown_' + ExpandoFlag ] = TRUE;
1201+ return enter;
1202+ })
1203+ .bind({
1204+ 'keyup.autoComplete': function( event ) {
1205+ // If autoComplete has been disabled or keyup prevention
1206+ // flag has be set, prevent input events
1207+ if ( ! ACData.active || LastEvent[ 'keydown_' + ExpandoFlag ] ) {
1208+ return TRUE;
1209+ }
1210+
1211+ // If no special operations were run on keydown,
1212+ // allow for regular text searching
1213+ inputval = $input.val();
1214+ var key = ( LastEvent = event ).keyCode, val = separator ? inputval.split( separator ).pop() : inputval;
1215+
1216+ // Still check to make sure 'enter' wasn't pressed
1217+ if ( key != KEY.enter ) {
1218+
1219+ // Caching key value
1220+ cache.val = settings.inputControl === undefined ? val :
1221+ settings.inputControl.apply( self, settings.backwardsCompatible ?
1222+ [ val, key, $ul, event, settings, cache ] :
1223+ [ event, {
1224+ val: val,
1225+ key: key,
1226+ settings: settings,
1227+ cache: cache,
1228+ ul: $ul
1229+ }]
1230+ );
1231+
1232+ // Only send request if character length passes
1233+ if ( cache.val.length >= settings.minChars ) {
1234+ sendRequest( event, settings, cache, ( key === KEY.backspace || key === KEY.space ) );
1235+ }
1236+ // Remove list on backspace of small string
1237+ else if ( key == KEY.backspace ) {
1238+ $ul.html('').hide( event );
1239+ }
1240+ }
1241+ },
1242+
1243+ 'blur.autoComplete': function( event ) {
1244+ // If autoComplete has been disabled or the drop list
1245+ // is still open, prevent input events
1246+ if ( ! ACData.active || ulOpen ) {
1247+ return TRUE;
1248+ }
1249+
1250+ // Only push undefined index onto order stack
1251+ // if not already there (in-case multiple blur events occur)
1252+ if ( AutoComplete.order[0] !== undefined ) {
1253+ AutoComplete.order.unshift( undefined );
1254+ }
1255+
1256+ // Expose focus
1257+ AutoComplete.hasFocus = FALSE;
1258+ ACData.hasFocus = FALSE;
1259+ liFocus = -1;
1260+ $ul.hide( LastEvent = event );
1261+
1262+ // Trigger both the global and element specific blur events
1263+ if ( AutoComplete.blur ) {
1264+ AutoComplete.blur.call( self, event, { settings: settings, cache: cache, ul: $ul } );
1265+ }
1266+
1267+ if ( settings.onBlur ) {
1268+ settings.onBlur.apply( self, settings.backwardsCompatible ?
1269+ [ inputval, $ul, event, settings, cache ] : [ event, {
1270+ val: inputval,
1271+ settings: settings,
1272+ cache: cache,
1273+ ul: $ul
1274+ }]
1275+ );
1276+ }
1277+ },
1278+
1279+ 'focus.autoComplete': function( event, flag ) {
1280+ // Prevent inner focus events if caused by autoComplete inner functionality
1281+ // Also, because IE triggers focus AND closes the drop list before form submission,
1282+ // keep the select flag by not reseting the last event
1283+ if ( ! ACData.active || ( ACData.hasFocus && flag === ExpandoFlag ) || LastEvent[ 'enter_' + ExpandoFlag ] ) {
1284+ return TRUE;
1285+ }
1286+
1287+ if ( inputIndex !== $ul.data( 'ac-input-index' ) ) {
1288+ $ul.html('').hide( event );
1289+ }
1290+
1291+ // Overwrite undefined index pushed on by the blur event
1292+ if ( AutoComplete.order[0] === undefined ) {
1293+ if ( AutoComplete.order[1] === inputIndex ) {
1294+ AutoComplete.order.shift();
1295+ } else {
1296+ AutoComplete.order[0] = inputIndex;
1297+ }
1298+ }
1299+ else if ( AutoComplete.order[0] != inputIndex && AutoComplete.order[1] != inputIndex ) {
1300+ AutoComplete.order.unshift( inputIndex );
1301+ }
1302+
1303+ if ( AutoComplete.defaults.cacheLimit !== -1 && AutoComplete.order.length > AutoComplete.defaults.cacheLimit ) {
1304+ AutoComplete.order.pop();
1305+ }
1306+
1307+ // Expose focus
1308+ AutoComplete.hasFocus = TRUE;
1309+ ACData.hasFocus = TRUE;
1310+ LastEvent = event;
1311+
1312+ // Trigger both the global and element specific focus events
1313+ if ( AutoComplete.focus ) {
1314+ AutoComplete.focus.call( self, event, { settings: settings, cache: cache, ul: $ul } );
1315+ }
1316+
1317+ if ( settings.onFocus ) {
1318+ settings.onFocus.apply( self,
1319+ settings.backwardsCompatible ? [ $ul, event, settings, cache ] : [ event, {
1320+ settings: settings,
1321+ cache: cache,
1322+ ul: $ul
1323+ }]
1324+ );
1325+ }
1326+ },
1327+
1328+ /**
1329+ * Autocomplete Custom Methods (Extensions off autoComplete event)
1330+ */
1331+ // Catches document click events from the global scope
1332+ 'autoComplete.document-click': function( e, event ) {
1333+ if ( ACData.active && ulOpen &&
1334+ // Double check the event timestamps to ensure there isn't a delayed reaction from a button
1335+ ( ! LastEvent || event.timeStamp - LastEvent.timeStamp > 200 ) &&
1336+ // Check the target after all other checks are passed (less processing)
1337+ $( event.target ).closest( 'ul' ).data( 'ac-input-index' ) !== inputIndex ) {
1338+ $ul.hide( LastEvent = event );
1339+ $input.blur();
1340+ }
1341+ },
1342+
1343+ // Catches form submission ( so only one event is attached to the form )
1344+ 'autoComplete.form-submit': function( e, event, form ) {
1345+ if ( ! ACData.active ) {
1346+ return TRUE;
1347+ }
1348+
1349+ LastEvent = event;
1350+
1351+ // Because IE triggers focus AND closes the drop list before form submission,
1352+ // tracking enter is set on the keydown event
1353+ return settings.preventEnterSubmit && ( ulOpen || LastEvent[ 'enter_' + ExpandoFlag ] ) ? FALSE :
1354+ settings.onSubmit === undefined ? TRUE :
1355+ settings.onSubmit.call( self, event, { form: form, settings: settings, cache: cache, ul: $ul } );
1356+ },
1357+
1358+ // Catch mouseovers on the drop down element
1359+ 'autoComplete.ul-mouseenter': function( e, event, li ) {
1360+ if ( $li ) {
1361+ $li.removeClass( settings.rollover );
1362+ }
1363+
1364+ $li = $( li ).addClass( settings.rollover );
1365+ liFocus = $elems.index( li );
1366+ liData = currentList[ liFocus ];
1367+ view = $ul.scrollTop() + ulHeight;
1368+ LastEvent = event;
1369+
1370+ if ( settings.onRollover ) {
1371+ settings.onRollover.apply( self, settings.backwardsCompatible ?
1372+ [ liData, $li, $ul, event, settings, cache ] :
1373+ [ event, {
1374+ data: liData,
1375+ li: $li,
1376+ settings: settings,
1377+ cache: cache,
1378+ ul: $ul
1379+ }]
1380+ );
1381+ }
1382+ },
1383+
1384+ // Catch click events on the drop down
1385+ 'autoComplete.ul-click': function( e, event ) {
1386+ // Refocus the input box and pass flag to prevent inner focus events
1387+ $input.trigger( 'focus', [ ExpandoFlag ] );
1388+
1389+ // Check against separator for input value
1390+ $input.val( inputval === separator ?
1391+ inputval.substr( 0, inputval.length - inputval.split( separator ).pop().length ) + liData.value + separator :
1392+ liData.value
1393+ );
1394+
1395+ $ul.hide( LastEvent = event );
1396+ autoFill();
1397+
1398+ if ( settings.onSelect ) {
1399+ settings.onSelect.apply( self, settings.backwardsCompatible ?
1400+ [ liData, $li, $ul, event, settings, cache ] :
1401+ [ event, {
1402+ data: liData,
1403+ li: $li,
1404+ settings: settings,
1405+ cache: cache,
1406+ ul: $ul
1407+ }]
1408+ );
1409+ }
1410+ },
1411+
1412+ // Allow for change of settings at any point
1413+ 'autoComplete.settings': function( event, newSettings ) {
1414+ if ( ! ACData.active ) {
1415+ return TRUE;
1416+ }
1417+
1418+ var ret, $el;
1419+ LastEvent = event;
1420+
1421+ // Give access to current settings and cache
1422+ if ( $.isFunction( newSettings ) ) {
1423+ ret = newSettings.apply( self, settings.backwardsCompatible ?
1424+ [ settings, cache, $ul, event ] : [ event, { settings: settings, cache: cache, ul: $ul } ]
1425+ );
1426+
1427+ // Allow for extending of settings/cache based off function return values
1428+ if ( $.isArray( ret ) && ret[0] !== undefined ) {
1429+ $.extend( TRUE, settings, ret[0] || settings );
1430+ $.extend( TRUE, cache, ret[1] || cache );
1431+ }
1432+ } else {
1433+ $.extend( TRUE, settings, newSettings || {} );
1434+ }
1435+
1436+ // Change the drop down if dev want's a differen't class attached
1437+ $ul = ! settings.newList && $ul.hasClass( settings.list ) ? $ul :
1438+ ! settings.newList && ( $el = rootjQuery.find( 'ul.' + settings.list ).eq( 0 ) ).length ?
1439+ $el.bgiframe( settings.bgiframe ) :
1440+ $('<ul/>').appendTo('body').addClass( settings.list )
1441+ .bgiframe( settings.bgiframe ).hide().data( 'ac-selfmade', TRUE );
1442+
1443+ // Custom drop list modifications
1444+ newUl();
1445+
1446+ // Change case here so it doesn't have to be done on every request
1447+ settings.requestType = settings.requestType.toUpperCase();
1448+
1449+ // Local copy of the seperator for faster referencing
1450+ separator = settings.multiple ? settings.multipleSeparator : undefined;
1451+
1452+ // Just to be sure, reset the settings object into the data storage
1453+ ACData.settings = settings;
1454+ },
1455+
1456+ // Clears the Cache & requests (requests can be blocked from clearing)
1457+ 'autoComplete.flush': function( event, cacheOnly ) {
1458+ if ( ! ACData.active ) {
1459+ return TRUE;
1460+ }
1461+
1462+ if ( ! cacheOnly ) {
1463+ requests = 0;
1464+ }
1465+
1466+ cache = { length: 0, val: undefined, list: {} };
1467+ LastEvent = event;
1468+ },
1469+
1470+ // External button trigger for ajax requests
1471+ 'autoComplete.button-ajax': function( event, postData, cacheName ) {
1472+ if ( ! ACData.active ) {
1473+ return TRUE;
1474+ }
1475+
1476+ if ( typeof postData === 'string' ) {
1477+ cacheName = postData;
1478+ postData = {};
1479+ }
1480+
1481+ // Save off the last event before triggering focus on the off-chance
1482+ // it is needed by a secondary focus event
1483+ LastEvent = event;
1484+
1485+ // Refocus the input box, but pass flag to prevent inner focus events
1486+ $input.trigger( 'focus', [ ExpandoFlag ] );
1487+
1488+ // If no cache name is given, supply a non-common word
1489+ cache.val = cacheName || 'button-ajax_' + ExpandoFlag;
1490+
1491+ return sendRequest(
1492+ event,
1493+ $.extend( TRUE, {}, settings, { maxItems: -1, postData: postData || {} } ),
1494+ cache
1495+ );
1496+ },
1497+
1498+ // External button trigger for supplied data
1499+ 'autoComplete.button-supply': function( event, data, cacheName ) {
1500+ if ( ! ACData.active ) {
1501+ return TRUE;
1502+ }
1503+
1504+ if ( typeof data === 'string' ) {
1505+ cacheName = data;
1506+ data = undefined;
1507+ }
1508+
1509+ // Again, save off event before triggering focus
1510+ LastEvent = event;
1511+
1512+ // Refocus the input box and pass flag to prevent inner focus events
1513+ $input.trigger( 'focus', [ ExpandoFlag ] );
1514+
1515+ // If no cache name is given, supply a non-common word
1516+ cache.val = cacheName || 'button-supply_' + ExpandoFlag;
1517+
1518+ // If no data is supplied, use data in settings
1519+ data = $.isArray( data ) ? data : settings.dataSupply;
1520+
1521+ return sendRequest(
1522+ event,
1523+ $.extend( TRUE, {}, settings, { maxItems: -1, dataSupply: data, formatSupply: allSupply } ),
1524+ cache
1525+ );
1526+ },
1527+
1528+ // Supply list directly into the result function
1529+ 'autoComplete.direct-supply': function( event, data, cacheName ) {
1530+ if ( ! ACData.active ) {
1531+ return TRUE;
1532+ }
1533+
1534+ if ( typeof data === 'string' ) {
1535+ cacheName = data;
1536+ data = undefined;
1537+ }
1538+
1539+ // Again, save off event before triggering focus
1540+ LastEvent = event;
1541+
1542+ // Refocus the input box and pass flag to prevent inner focus events
1543+ $input.trigger( 'focus', [ ExpandoFlag ] );
1544+
1545+ // If no cache name is given, supply a non-common word
1546+ cache.val = cacheName || 'direct-supply_' + ExpandoFlag;
1547+
1548+ // If no data is supplied, use data in settings
1549+ data = $.isArray( data ) && data.length ? data : settings.dataSupply;
1550+
1551+ // Load the results directly into the results function bypassing request holdups
1552+ return loadResults(
1553+ event,
1554+ data,
1555+ $.extend( TRUE, {}, settings, { maxItems: -1, dataSupply: data, formatSupply: allSupply } ),
1556+ cache
1557+ );
1558+ },
1559+
1560+ // Triggering autocomplete programatically
1561+ 'autoComplete.search': function( event, value ) {
1562+ if ( ! ACData.active ) {
1563+ return TRUE;
1564+ }
1565+
1566+ cache.val = value || '';
1567+ return sendRequest( LastEvent = event, settings, cache );
1568+ },
1569+
1570+ // Add jquery-ui like option access
1571+ 'autoComplete.option': function( event, name, value ) {
1572+ if ( ! ACData.active ) {
1573+ return TRUE;
1574+ }
1575+
1576+ LastEvent = event;
1577+ switch ( Slice.call( arguments ).length ) {
1578+ case 3:
1579+ settings[ name ] = value;
1580+ return value;
1581+ case 2:
1582+ return name === 'ul' ? $ul :
1583+ name === 'cache' ? cache :
1584+ name === 'xhr' ? xhr :
1585+ name === 'input' ? $input :
1586+ settings[ name ] || undefined;
1587+ default:
1588+ return settings;
1589+ }
1590+ },
1591+
1592+ // Add enabling event (only applicable after disable)
1593+ 'autoComplete.enable': function( event ) {
1594+ ACData.active = TRUE;
1595+ LastEvent = event;
1596+ },
1597+
1598+ // Add disable event
1599+ 'autoComplete.disable': function( event ) {
1600+ ACData.active = FALSE;
1601+ $ul.html('').hide( LastEvent = event );
1602+ },
1603+
1604+ // Add a destruction function
1605+ 'autoComplete.destroy': function( event ) {
1606+ var list = $ul.html('').hide( LastEvent = event ).data( 'ac-inputs' ) || {}, i;
1607+
1608+ // Remove all autoComplete specific data and events
1609+ $input.removeData( 'autoComplete' ).unbind( '.autoComplete autoComplete' );
1610+
1611+ // Remove form/drop list/document event catchers if possible
1612+ teardown( $input, inputIndex );
1613+
1614+ // Remove input from the drop down element of inputs
1615+ list[ inputIndex ] = undefined;
1616+
1617+ // Go through the drop down element and see if any other inputs are attached to it
1618+ for ( i in list ) {
1619+ if ( list.hasOwnProperty( i ) && list[ i ] === TRUE ) {
1620+ return LastEvent;
1621+ }
1622+ }
1623+
1624+ // Remove the element from the DOM if self created
1625+ if ( $ul.data( 'ac-selfmade' ) === TRUE ) {
1626+ $ul.remove();
1627+ }
1628+ // Kill all data associated with autoComplete for a cleaned drop down element
1629+ else {
1630+ $ul.removeData( 'autoComplete' ).removeData( 'ac-input-index' ).removeData( 'ac-inputs' );
1631+ }
1632+ }
1633+ });
1634+
1635+ // Ajax/Cache Request
1636+ function sendRequest( event, settings, cache, backSpace, timeout ) {
1637+ // Merely setting max requests still allows usage of cache and supplied data,
1638+ // this 'Deep' option prevents those scenarios if needed
1639+ if ( settings.maxRequestsDeep === true && requests >= settings.maxRequests ) {
1640+ return FALSE;
1641+ }
1642+
1643+ if ( settings.spinner ) {
1644+ settings.spinner.call( self, event, { active: TRUE, settings: settings, cache: cache, ul: $ul } );
1645+ }
1646+
1647+ if ( timeid ) {
1648+ timeid = clearTimeout( timeid );
1649+ }
1650+
1651+ // Call send request again with timeout flag if on delay
1652+ if ( settings.delay > 0 && timeout === undefined ) {
1653+ timeid = window.setTimeout(function(){
1654+ sendRequest( event, settings, cache, backSpace, TRUE );
1655+ }, settings.delay );
1656+ return timeid;
1657+ }
1658+
1659+ // Abort previous request incase it's still running
1660+ if ( xhr ) {
1661+ xhr.abort();
1662+ }
1663+
1664+ // Load from cache if possible
1665+ if ( settings.useCache && $.isArray( cache.list[ cache.val ] ) ) {
1666+ return loadResults( event, cache.list[ cache.val ], settings, cache, backSpace );
1667+ }
1668+
1669+ // Use user supplied data when defined
1670+ if ( settings.dataSupply.length ) {
1671+ return userSuppliedData( event, settings, cache, backSpace );
1672+ }
1673+
1674+ // Check Max requests first before sending request
1675+ if ( settings.maxRequests && ++requests >= settings.maxRequests ) {
1676+ $ul.html('').hide( event );
1677+
1678+ if ( settings.spinner ) {
1679+ settings.spinner.call( self, event, { active: FALSE, settings: settings, cache: cache, ul: $ul } );
1680+ }
1681+
1682+ if ( settings.onMaxRequest && requests === settings.maxRequests ) {
1683+ return settings.onMaxRequest.apply( self, settings.backwardsCompatible ?
1684+ [ cache.val, $ul, event, inputval, settings, cache ] :
1685+ [ event, {
1686+ search: cache.val,
1687+ val: inputval,
1688+ settings: settings,
1689+ cache: cache,
1690+ ul: $ul
1691+ }]
1692+ );
1693+ }
1694+
1695+ return FALSE;
1696+ }
1697+
1698+ settings.postData[ settings.postVar ] = cache.val;
1699+ xhr = $.ajax({
1700+ type: settings.requestType,
1701+ url: settings.ajax,
1702+ cache: settings.ajaxCache,
1703+ dataType: 'json',
1704+
1705+ // Send personalised data
1706+ data: settings.postFormat ?
1707+ settings.postFormat.call( self, event, {
1708+ data: settings.postData,
1709+ search: cache.val,
1710+ val: inputval,
1711+ settings: settings,
1712+ cache: cache,
1713+ ul: $ul
1714+ }) :
1715+ settings.postData,
1716+
1717+ success: function( list ) {
1718+ loadResults( event, list, settings, cache, backSpace );
1719+ },
1720+
1721+ error: function() {
1722+ $ul.html('').hide( event );
1723+ if ( settings.spinner ) {
1724+ settings.spinner.call( self, event, { active: FALSE, settings: settings, cache: cache, ul: $ul } );
1725+ }
1726+ }
1727+ });
1728+
1729+ return xhr;
1730+ }
1731+
1732+ // Parse User Supplied Data
1733+ function userSuppliedData( event, settings, cache, backSpace ) {
1734+ var list = [], args = [],
1735+ fn = $.isFunction( settings.dataFn ),
1736+ regex = fn ? undefined : new RegExp( '^'+cache.val, 'i' ),
1737+ items = 0, entry, i = -1, l = settings.dataSupply.length;
1738+
1739+ if ( settings.formatSupply ) {
1740+ list = settings.formatSupply.call( self, event, {
1741+ search: cache.val,
1742+ supply: settings.dataSupply,
1743+ settings: settings,
1744+ cache: cache,
1745+ ul: $ul
1746+ });
1747+ } else {
1748+ for ( ; ++i < l ; ) {
1749+ // Force object wrapper for entry
1750+ entry = settings.dataSupply[i];
1751+ entry = entry && typeof entry.value === 'string' ? entry : { value: entry };
1752+
1753+ // Setup arguments for dataFn in a backwards compatible way if needed
1754+ args = settings.backwardsCompatible ?
1755+ [ cache.val, entry.value, list, i, settings.dataSupply, $ul, event, settings, cache ] :
1756+ [ event, {
1757+ search: cache.val,
1758+ entry: entry.value,
1759+ list: list,
1760+ i: i,
1761+ supply: settings.dataSupply,
1762+ settings: settings,
1763+ cache: cache,
1764+ ul: $ul
1765+ }];
1766+
1767+ // If user supplied function, use that, otherwise test with default regex
1768+ if ( ( fn && settings.dataFn.apply( self, args ) ) || ( ! fn && entry.value.match( regex ) ) ) {
1769+ // Reduce browser load by breaking on limit if it exists
1770+ if ( settings.maxItems > -1 && ++items > settings.maxItems ) {
1771+ break;
1772+ }
1773+ list.push( entry );
1774+ }
1775+ }
1776+ }
1777+
1778+ // Use normal load functionality
1779+ return loadResults( event, list, settings, cache, backSpace );
1780+ }
1781+
1782+ // Key element Selection
1783+ function select( event ) {
1784+ // Ensure the select function only gets fired when list of open
1785+ if ( ulOpen ) {
1786+ if ( settings.onSelect ) {
1787+ settings.onSelect.apply( self, settings.backwardsCompatible ?
1788+ [ liData, $li, $ul, event, settings, cache ] :
1789+ [ event, {
1790+ data: liData,
1791+ li: $li,
1792+ settings: settings,
1793+ cache: cache,
1794+ ul: $ul
1795+ }]
1796+ );
1797+ }
1798+
1799+ autoFill();
1800+ inputval = $input.val();
1801+
1802+ // Because IE triggers focus AND closes the drop list before form submission
1803+ // attach a flag on 'enter' selection
1804+ if ( LastEvent.type === 'keydown' ) {
1805+ LastEvent[ 'enter_' + ExpandoFlag ] = TRUE;
1806+ }
1807+
1808+ $ul.hide( event );
1809+ }
1810+
1811+ $li = undefined;
1812+ }
1813+
1814+ // Key direction up
1815+ function up( event ) {
1816+ if ( $li ) {
1817+ $li.removeClass( settings.rollover );
1818+ }
1819+
1820+ $ul.show( event );
1821+ $li = $elems.eq( liFocus ).addClass( settings.rollover );
1822+ liData = currentList[ liFocus ];
1823+
1824+ if ( ! $li.length || ! liData ) {
1825+ return FALSE;
1826+ }
1827+
1828+ autoFill( liData.value );
1829+ if ( settings.onRollover ) {
1830+ settings.onRollover.apply( self, settings.backwardsCompatible ?
1831+ [ liData, $li, $ul, event, settings, cache ] :
1832+ [ event, {
1833+ data: liData,
1834+ li: $li,
1835+ settings: settings,
1836+ cache: cache,
1837+ ul: $ul
1838+ }]
1839+ );
1840+ }
1841+
1842+ // Scrolling
1843+ var scroll = liFocus * liHeight;
1844+ if ( scroll < view - ulHeight ) {
1845+ view = scroll + ulHeight;
1846+ $ul.scrollTop( scroll );
1847+ }
1848+ }
1849+
1850+ // Key direction down
1851+ function down( event ) {
1852+ if ( $li ) {
1853+ $li.removeClass( settings.rollover );
1854+ }
1855+
1856+ $ul.show( event );
1857+ $li = $elems.eq( liFocus ).addClass( settings.rollover );
1858+ liData = currentList[ liFocus ];
1859+
1860+ if ( ! $li.length || ! liData ) {
1861+ return FALSE;
1862+ }
1863+
1864+ autoFill( liData.value );
1865+
1866+ // Scrolling
1867+ var scroll = ( liFocus + 1 ) * liHeight;
1868+ if ( scroll > view ) {
1869+ $ul.scrollTop( ( view = scroll ) - ulHeight );
1870+ }
1871+
1872+ if ( settings.onRollover ) {
1873+ settings.onRollover.apply( self, settings.backwardsCompatible ?
1874+ [ liData, $li, $ul, event, settings, cache ] : [ event, {
1875+ data: liData,
1876+ li: $li,
1877+ settings: settings,
1878+ cache: cache,
1879+ ul: $ul
1880+ }]
1881+ );
1882+ }
1883+ }
1884+
1885+ // Attach new show/hide functionality to only the ul object (so not to infect all of jQuery),
1886+ // And also attach event handlers if not already done so
1887+ function newUl() {
1888+ var hide = $ul.hide, show = $ul.show, list = $ul.data( 'ac-inputs' ) || {};
1889+
1890+ if ( ! $ul[ ExpandoFlag ] ) {
1891+ $ul.hide = function( event, speed, callback ) {
1892+ if ( settings.onHide && ulOpen ) {
1893+ settings.onHide.call( self, event, { ul: $ul, settings: settings, cache: cache } );
1894+ }
1895+
1896+ ulOpen = FALSE;
1897+ return hide.call( $ul, speed, callback );
1898+ };
1899+
1900+ $ul.show = function( event, speed, callback ) {
1901+ if ( settings.onShow && ! ulOpen ) {
1902+ settings.onShow.call( self, event, { ul: $ul, settings: settings, cache: cache } );
1903+ }
1904+
1905+ ulOpen = TRUE;
1906+ return show.call( $ul, speed, callback );
1907+ };
1908+
1909+ // A flag must be attached to the $ul cached object
1910+ $ul[ ExpandoFlag ] = TRUE;
1911+ }
1912+
1913+ // Attach global handlers for event delegation (So there is no more loss time in unbinding and rebinding)
1914+ if ( $ul.data( 'autoComplete' ) !== TRUE ) {
1915+ $ul.data( 'autoComplete', TRUE )
1916+ .delegate( 'li', 'mouseenter.autoComplete', function( event ) {
1917+ AutoComplete.getFocus( TRUE ).trigger( 'autoComplete.ul-mouseenter', [ event, this ] );
1918+ })
1919+ .bind( 'click.autoComplete', function( event ) {
1920+ AutoComplete.getFocus( TRUE ).trigger( 'autoComplete.ul-click', [ event ] );
1921+ return FALSE;
1922+ });
1923+ }
1924+
1925+ list[ inputIndex ] = TRUE;
1926+ $ul.data( 'ac-inputs', list );
1927+ }
1928+
1929+ // Auto-fill the input
1930+ // Credit to Jörn Zaefferer @ http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/
1931+ // and http://www.pengoworks.com/workshop/jquery/autocomplete.htm for this functionality
1932+ function autoFill( val ) {
1933+ var start, end, range;
1934+
1935+ // Set starting and ending points based on values
1936+ if ( val === undefined || val === '' ) {
1937+ start = end = $input.val().length;
1938+ } else {
1939+ if ( separator ) {
1940+ val = inputval.substr( 0, inputval.length - inputval.split( separator ).pop().length ) + val + separator;
1941+ }
1942+
1943+ start = inputval.length;
1944+ end = val.length;
1945+ $input.val( val );
1946+ }
1947+
1948+ // Create selection if allowed
1949+ if ( ! settings.autoFill || start > end ) {
1950+ return FALSE;
1951+ }
1952+ else if ( self.createTextRange ) {
1953+ range = self.createTextRange();
1954+ if ( val === undefined ) {
1955+ range.move( 'character', start );
1956+ range.select();
1957+ } else {
1958+ range.collapse( TRUE );
1959+ range.moveStart( 'character', start );
1960+ range.moveEnd( 'character', end );
1961+ range.select();
1962+ }
1963+ }
1964+ else if ( self.setSelectionRange ) {
1965+ self.setSelectionRange( start, end );
1966+ }
1967+ else if ( self.selectionStart ) {
1968+ self.selectionStart = start;
1969+ self.selectionEnd = end;
1970+ }
1971+ }
1972+
1973+ // List Functionality
1974+ function loadResults( event, list, settings, cache, backSpace ) {
1975+ // Allow another level of result handling
1976+ currentList = settings.onLoad ?
1977+ settings.onLoad.call( self, event, { list: list, settings: settings, cache: cache, ul: $ul } ) : list;
1978+
1979+ // Tell spinner function to stop if set
1980+ if ( settings.spinner ) {
1981+ settings.spinner.call( self, event, { active: FALSE, settings: settings, cache: cache, ul: $ul } );
1982+ }
1983+
1984+ // Store results into the cache if allowed
1985+ if ( settings.useCache && ! $.isArray( cache.list[ cache.val ] ) ) {
1986+ cache.length++;
1987+ cache.list[ cache.val ] = list;
1988+
1989+ // Clear cache if necessary
1990+ if ( settings.cacheLimit !== -1 && cache.length > settings.cacheLimit ) {
1991+ cache.list = {};
1992+ cache.length = 0;
1993+ }
1994+ }
1995+
1996+ // Ensure there is a list
1997+ if ( ! currentList || currentList.length < 1 ) {
1998+ return $ul.html('').hide( event );
1999+ }
2000+
2001+ // Refocus list element
2002+ liFocus = -1;
2003+
2004+ // Initialize Vars together (save bytes)
2005+ var offset = $input.offset(), // Input position
2006+ container = [], // Container for list elements
2007+ items = 0, i = -1, striped = FALSE, length = currentList.length; // Loop Items
2008+
2009+ if ( settings.onListFormat ) {
2010+ settings.onListFormat.call( self, event, { list: currentList, settings: settings, cache: cache, ul: $ul } );
2011+ }
2012+ else {
2013+ // Push items onto container
2014+ for ( ; ++i < length; ) {
2015+ if ( currentList[i].value ) {
2016+ if ( settings.maxItems > -1 && ++items > settings.maxItems ) {
2017+ break;
2018+ }
2019+
2020+ container.push(
2021+ settings.striped && striped ? '<li class="' + settings.striped + '">' : '<li>',
2022+ currentList[i].display || currentList[i].value,
2023+ '</li>'
2024+ );
2025+
2026+ striped = ! striped;
2027+ }
2028+ }
2029+ $ul.html( container.join('') );
2030+ }
2031+
2032+ // Cache the list items
2033+ $elems = $ul.children( 'li' );
2034+
2035+ // Autofill input with first entry
2036+ if ( settings.autoFill && ! backSpace ) {
2037+ liFocus = 0;
2038+ liData = currentList[ 0 ];
2039+ autoFill( liData.value );
2040+ $li = $elems.eq( 0 ).addClass( settings.rollover );
2041+ }
2042+
2043+ // Align the drop down element
2044+ $ul.data( 'ac-input-index', inputIndex ).scrollTop( 0 ).css({
2045+ top: offset.top + $input.outerHeight(),
2046+ left: offset.left,
2047+ width: settings.width
2048+ })
2049+ // The drop list has to be shown before maxHeight can be configured
2050+ .show( event );
2051+
2052+ // Log li height for less computation
2053+ liHeight = $elems.eq( 0 ).outerHeight();
2054+
2055+ // If Max Height specified, control it
2056+ if ( settings.maxHeight ) {
2057+ $ul.css({
2058+ height: liHeight * $elems.length > settings.maxHeight ? settings.maxHeight : 'auto',
2059+ overflow: 'auto'
2060+ });
2061+ }
2062+
2063+ // ulHeight gets manipulated, so assign to viewport seperately
2064+ // so referencing conflicts don't override viewport
2065+ ulHeight = $ul.outerHeight();
2066+ view = ulHeight;
2067+
2068+ // Number of elements per viewport
2069+ liPerView = liHeight === 0 ? 0 : Math.floor( view / liHeight );
2070+
2071+ // Include amount of time it took to load the list
2072+ // and run modifications
2073+ LastEvent.timeStamp = ( new Date() ).getTime();
2074+ }
2075+
2076+ // Custom modifications to the drop down element
2077+ newUl();
2078+
2079+ // Do case change on initialization so it's not run on every request
2080+ settings.requestType = settings.requestType.toUpperCase();
2081+
2082+ // Local quick copy of the seperator (so we don't have to run this check every time)
2083+ separator = settings.multiple ? settings.multipleSeparator : undefined;
2084+
2085+ // Expose copies of both the input element and the cached jQuery version
2086+ AutoComplete.stack[ inputIndex ] = self;
2087+ AutoComplete.jqStack[ inputIndex ] = $input;
2088+
2089+ // Form and Document event attachment
2090+ setup( $input, inputIndex );
2091+ };
2092+
2093+})( jQuery, window || this );
2094
2095=== modified file 'website/views/website_templates.xml'
2096--- website/views/website_templates.xml 2014-02-21 10:47:25 +0000
2097+++ website/views/website_templates.xml 2014-02-26 06:23:38 +0000
2098@@ -271,7 +271,9 @@
2099 <script type="text/javascript" src="/website/static/lib/MutationObservers/test/sidetable.js"></script>
2100 <script type="text/javascript" src='/website/static/lib/nearest/jquery.nearest.js'></script>
2101 <script type="text/javascript" src="/website/static/lib/MutationObservers/MutationObserver.js"></script>
2102-
2103+ <!-- Add Auto complete Library -->
2104+ <script type="text/javascript" src="/website/static/lib/autocomplete/jquery.auto-complete.js"></script>
2105+
2106 <script type="text/javascript" src="/website/static/src/js/website.editor.js"></script>
2107 <script type="text/javascript" src="/website/static/src/js/website.editor.newpage.js" groups="base.group_website_designer"></script>
2108 <script type="text/javascript" src="/website/static/src/js/website.menu.js" groups="base.group_website_designer"></script>
2109
2110=== modified file 'website_quote/data/website_quotation_data.xml'
2111--- website_quote/data/website_quotation_data.xml 2014-01-25 23:25:25 +0000
2112+++ website_quote/data/website_quotation_data.xml 2014-02-26 06:23:38 +0000
2113@@ -63,7 +63,7 @@
2114 ${object.company_id.zip} ${object.company_id.city}<br/>
2115 % endif
2116 % if object.company_id.country_id:
2117- ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
2118+ ${object.company_id.state}<br/>
2119 % endif
2120 </span>
2121 % if object.company_id.phone:
2122
2123=== modified file 'website_sale/controllers/main.py'
2124--- website_sale/controllers/main.py 2014-02-25 09:05:06 +0000
2125+++ website_sale/controllers/main.py 2014-02-26 06:23:38 +0000
2126@@ -15,11 +15,11 @@
2127
2128 class CheckoutInfo(object):
2129 mandatory_billing_fields = ["name", "phone", "email", "street", "city", "country_id", "zip"]
2130- optional_billing_fields = ["company", "state_id"]
2131+ optional_billing_fields = ["company", "state"]
2132 string_billing_fields = ["name", "phone", "email", "street", "city", "zip"]
2133
2134 mandatory_shipping_fields = ["shipping_name", "shipping_phone", "shipping_street", "shipping_city", "shipping_country_id", "shipping_zip"]
2135- optional_shipping_field = ["shipping_state_id"]
2136+ optional_shipping_field = ["shipping_state"]
2137 string_shipping_fields = ["shipping_name", "shipping_phone", "shipping_street", "shipping_city", "shipping_zip"]
2138
2139 def mandatory_fields(self):
2140@@ -41,7 +41,6 @@
2141 else:
2142 prefix = 'shipping_'
2143 result = dict((prefix + field_name, getattr(partner, field_name)) for field_name in self.string_billing_fields if getattr(partner, field_name))
2144- result[prefix + 'state_id'] = partner.state_id and partner.state_id.id or ''
2145 result[prefix + 'country_id'] = partner.country_id and partner.country_id.id or ''
2146 result[prefix + 'company'] = partner.parent_id and partner.parent_id.name or ''
2147 return result
2148@@ -406,14 +405,10 @@
2149 orm_country = registry.get('res.country')
2150 country_ids = orm_country.search(cr, SUPERUSER_ID, [], context=context)
2151 countries = orm_country.browse(cr, SUPERUSER_ID, country_ids, context)
2152- state_orm = registry.get('res.country.state')
2153- states_ids = state_orm.search(cr, SUPERUSER_ID, [], context=context)
2154- states = state_orm.browse(cr, SUPERUSER_ID, states_ids, context)
2155
2156 info = CheckoutInfo()
2157 values = {
2158 'countries': countries,
2159- 'states': states,
2160 'checkout': info.empty(),
2161 'shipping': post.get("shipping_different"),
2162 'error': {},
2163@@ -441,6 +436,16 @@
2164
2165 return request.website.render("website_sale.checkout", values)
2166
2167+ @http.route('/shop/get_country', type='json', auth='user', website=True)
2168+ def get_country(self, **post):
2169+ cr, uid, context, registry = request.cr, request.uid, request.context, request.registry
2170+ orm_country = registry.get('res.country')
2171+ country_ids = orm_country.search(cr, uid, [], context=context)
2172+ countries = {}
2173+ for country in orm_country.browse(cr, uid, country_ids, context):
2174+ countries.update({country.id : country.name})
2175+ return countries
2176+
2177 @http.route(['/shop/confirm_order/'], type='http', auth="public", website=True, multilang=True)
2178 def confirm_order(self, **post):
2179 cr, uid, context, registry = request.cr, request.uid, request.context, request.registry
2180@@ -459,16 +464,11 @@
2181 orm_partner = registry.get('res.partner')
2182 orm_user = registry.get('res.users')
2183 orm_country = registry.get('res.country')
2184- country_ids = orm_country.search(cr, SUPERUSER_ID, [], context=context)
2185- countries = orm_country.browse(cr, SUPERUSER_ID, country_ids, context)
2186- orm_state = registry.get('res.country.state')
2187- states_ids = orm_state.search(cr, SUPERUSER_ID, [], context=context)
2188- states = orm_state.browse(cr, SUPERUSER_ID, states_ids, context)
2189-
2190+ countries = orm_country.search(cr, SUPERUSER_ID, [('name','=',post['country_id'])], context=context)
2191+ post['country_id'] = countries[0]
2192+
2193 info = CheckoutInfo()
2194 values = {
2195- 'countries': countries,
2196- 'states': states,
2197 'checkout': info.empty(),
2198 'shipping': post.get("shipping_different"),
2199 'error': {},
2200@@ -513,6 +513,7 @@
2201
2202 shipping_id = None
2203 if post.get('shipping_different'):
2204+ shiping_id = orm_country.search(cr, SUPERUSER_ID, [('name','=',post['shipping_country_id'])], context=context)
2205 shipping_info = {
2206 'phone': post['shipping_phone'],
2207 'zip': post['shipping_zip'],
2208@@ -522,8 +523,7 @@
2209 'email': post['email'],
2210 'type': 'delivery',
2211 'parent_id': partner_id,
2212- 'country_id': post['shipping_country_id'],
2213- 'state_id': post['shipping_state_id'],
2214+ 'shipping_country_id': shiping_id[0],
2215 }
2216 domain = [(key, '_id' in key and '=' or 'ilike', '_id' in key and value and int(value) or value)
2217 for key, value in shipping_info.items() if key in info.mandatory_billing_fields + ["type", "parent_id"]]
2218@@ -670,7 +670,7 @@
2219 if not tx_ids:
2220 if order.amount_total:
2221 return {
2222- 'state': 'error',
2223+ 'f': 'error',
2224 'message': '<p>There seems to be an error with your request.</p>',
2225 }
2226 else:
2227
2228=== modified file 'website_sale/static/src/js/website_sale.js'
2229--- website_sale/static/src/js/website_sale.js 2014-02-06 14:07:46 +0000
2230+++ website_sale/static/src/js/website_sale.js 2014-02-26 06:23:38 +0000
2231@@ -6,7 +6,16 @@
2232 $shippingDifferent.change(function () {
2233 $(".oe_website_sale .js_shipping").toggle();
2234 });
2235-
2236+
2237+ openerp.jsonRpc('/shop/get_country', 'call', {}).then(function (countries){
2238+ var st = new Array();
2239+ $.each(countries, function(s, t) {
2240+ st.push(t);
2241+ });
2242+ $('input[name=country_id]').autocomplete({source: st});
2243+ $('input[name=shipping_country_id]').autocomplete({source: st});
2244+ });
2245+
2246 // change for css
2247 $(document).on('mouseup', '.js_publish', function (ev) {
2248 $(ev.currentTarget).parents(".thumbnail").toggleClass("disabled");
2249
2250=== modified file 'website_sale/views/website_sale.xml'
2251--- website_sale/views/website_sale.xml 2014-02-20 16:38:15 +0000
2252+++ website_sale/views/website_sale.xml 2014-02-26 06:23:38 +0000
2253@@ -762,23 +762,13 @@
2254 <label class="control-label" for="zip">Zip / Postal Code</label>
2255 <input type="text" name="zip" class="form-control" t-att-value="checkout.get('zip')"/>
2256 </div>
2257- <div t-attf-class="form-group #{error.get('state_id') and 'has-error' or ''} col-lg-6">
2258- <label class="control-label" for="state_id" style="font-weight: normal">State / Province</label>
2259- <select name="state_id" class="form-control">
2260- <option value="">select...</option>
2261- <t t-foreach="states or []" t-as="state">
2262- <option t-att-value="state.id" t-att-selected="state.id == checkout.get('state_id')"><t t-esc="state.name"/></option>
2263- </t>
2264- </select>
2265- </div>
2266+ <div t-attf-class="form-group #{error.get('state') and 'has-error' or ''} col-lg-6">
2267+ <label class="control-label" for="state"> State / Province...</label>
2268+ <input type="" name="state" class="form-control" t-att-value="state" />
2269+ </div>
2270 <div t-attf-class="form-group #{error.get('country_id') and 'has-error' or ''} col-lg-6">
2271- <label class="control-label" for="contact_name">Country</label>
2272- <select name="country_id" class="form-control">
2273- <option value="">Country...</option>
2274- <t t-foreach="countries or []" t-as="country">
2275- <option t-att-value="country.id" t-att-selected="country.id == checkout.get('country_id')"><t t-esc="country.name"/></option>
2276- </t>
2277- </select>
2278+ <label class="control-label" for="country_id">Country</label>
2279+ <input type="text" name="country_id" class="form-control" t-att-value="country_id" />
2280 </div>
2281
2282 <div class="clearfix"/>
2283@@ -814,24 +804,14 @@
2284 <label class="control-label" for="contact_name">Zip / Postal Code</label>
2285 <input type="text" name="shipping_zip" class="form-control" t-att-value="checkout.get('shipping_zip', '')"/>
2286 </div>
2287- <div t-attf-class="form-group #{error.get('shipping_state_id') and 'has-error' or ''} col-lg-6">
2288- <label class="control-label" for="contact_name" style="font-weight: normal">State / Province</label>
2289- <select name="shipping_state_id" class="form-control">
2290- <option value="">State / Province...</option>
2291- <t t-foreach="states or []" t-as="state">
2292- <option t-att-value="state.id" t-att-selected="state.id == checkout.get('shipping_state_id')"><t t-esc="state.name"/></option>
2293- </t>
2294- </select>
2295- </div>
2296+ <div t-attf-class="form-group #{error.get('shipping_state') and 'has-error' or ''} col-lg-6">
2297+ <label class="control-label" for="shipping_state"> State / Province...</label>
2298+ <input type="" name="shipping_state" class="form-control" t-att-value="shipping_state" />
2299+ </div>
2300 <div t-attf-class="form-group #{error.get('shipping_country_id') and 'has-error' or ''} col-lg-6">
2301- <label class="control-label" for="contact_name">Country</label>
2302- <select name="shipping_country_id" class="form-control">
2303- <option value="">Country...</option>
2304- <t t-foreach="countries or []" t-as="country">
2305- <option t-att-value="country.id" t-att-selected="country.id == checkout.get('shipping_country_id')"><t t-esc="country.name"/></option>
2306- </t>
2307- </select>
2308- </div>
2309+ <label class="control-label" for="shipping_country_id">Country</label>
2310+ <input type="text" name="shipping_country_id" class="form-control" t-att-value="shipping_country_id" />
2311+ </div>
2312 </div>
2313 <button type="submit" class="btn btn-default btn-primary pull-right mb32">Confirm <span class="fa fa-long-arrow-right"/></button>
2314 </div>

Subscribers

People subscribed via source and target branches

to all changes: