2 * This script refer to:
3 * Title: International Telephone Input
4 * Author: Jack O'Connor
5 * Code version: v12.1.12
6 * Availability: https://github.com/jackocnr/intl-tel-input.git
10 * @class Roo.bootstrap.PhoneInput
11 * @extends Roo.bootstrap.TriggerField
12 * An input with International dial-code selection
14 * @cfg {String} defaultDialCode default '+852'
15 * @cfg {Array} preferedCountries default []
18 * Create a new PhoneInput.
19 * @param {Object} config Configuration options
22 Roo.bootstrap.PhoneInput = function(config) {
23 Roo.bootstrap.PhoneInput.superclass.constructor.call(this, config);
26 Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
32 selectedClass: 'active',
34 invalidClass : "has-warning",
36 validClass: 'has-success',
38 allowed: '0123456789+',
40 defaultDialCode: '+852',
42 preferedCountries: false,
44 //white list / black list for countries?
46 getAutoCreate : function()
48 var data = Roo.bootstrap.PhoneInputData();
49 var align = this.labelAlign || this.parentLabelAlign();
52 this.allCountries = [];
53 this.dialCodeMapping = [];
55 for (var i = 0; i < data.length; i++) {
57 this.allCountries[i] = {
62 areaCodes: c[4] || null
64 this.dialCodeMapping[c[2]] = {
68 areaCodes: c[4] || null
80 cls : 'form-control tel-input',
81 autocomplete: 'new-password'
87 cls: 'hidden-tel-input'
91 hiddenInput.name = this.name;
95 input.disabled = true;
98 var flag_container = {
115 cls: this.hasFeedback ? 'has-feedback' : '',
121 cls: 'dial-code-holder',
128 cls: 'roo-select2-container input-group',
135 if (this.fieldLabel.length) {
138 tooltip: 'This field is required'
144 cls: 'control-label',
150 html: this.fieldLabel
153 indicator.cls = 'roo-required-indicator text-danger fa fa-lg fa-star left-indicator';
159 if(this.indicatorpos == 'right') {
160 indicator.cls = 'roo-required-indicator text-danger fa fa-lg fa-star right-indicator';
167 if(align == 'left') {
175 if(this.labelWidth > 12){
176 label.style = "width: " + this.labelWidth + 'px';
178 if(this.labelWidth < 13 && this.labelmd == 0){
179 this.labelmd = this.labelWidth;
181 if(this.labellg > 0){
182 label.cls += ' col-lg-' + this.labellg;
183 input.cls += ' col-lg-' + (12 - this.labellg);
185 if(this.labelmd > 0){
186 label.cls += ' col-md-' + this.labelmd;
187 container.cls += ' col-md-' + (12 - this.labelmd);
189 if(this.labelsm > 0){
190 label.cls += ' col-sm-' + this.labelsm;
191 container.cls += ' col-sm-' + (12 - this.labelsm);
193 if(this.labelxs > 0){
194 label.cls += ' col-xs-' + this.labelxs;
195 container.cls += ' col-xs-' + (12 - this.labelxs);
207 ['xs','sm','md','lg'].map(function(size){
208 if (settings[size]) {
209 cfg.cls += ' col-' + size + '-' + settings[size];
213 this.store = new Roo.data.Store({
214 proxy : new Roo.data.MemoryProxy({}),
215 reader : new Roo.data.JsonReader({
234 'name' : 'areaCodes',
241 if(!this.preferedCountries) {
242 this.preferedCountries = [
249 var p = this.preferedCountries.reverse();
252 for (var i = 0; i < p.length; i++) {
253 for (var j = 0; j < this.allCountries.length; j++) {
254 if(this.allCountries[j].iso2 == p[i]) {
255 var t = this.allCountries[j];
256 this.allCountries.splice(j,1);
257 this.allCountries.unshift(t);
263 this.store.proxy.data = {
265 data: this.allCountries
271 initEvents : function()
274 Roo.bootstrap.PhoneInput.superclass.initEvents.call(this);
276 this.indicator = this.indicatorEl();
277 this.flag = this.flagEl();
278 this.dialCodeHolder = this.dialCodeHolderEl();
280 this.trigger = this.el.select('div.flag-box',true).first();
281 this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});
286 var lw = _this.listWidth || Math.max(_this.inputEl().getWidth(), _this.minListWidth);
287 _this.list.setWidth(lw);
290 this.list.on('mouseover', this.onViewOver, this);
291 this.list.on('mousemove', this.onViewMove, this);
292 //this.list.on('scroll', this.onViewScroll, this);
293 // this.inputEl().on("keyup", this.onKeyUp, this);
294 this.inputEl().on("keypress", this.onKeyPress, this);
296 this.tpl = '<li><a href="#"><div class="flag {iso2}"></div>{name} <span class="dial-code">+{dialCode}</span></a></li>';
298 this.view = new Roo.View(this.list, this.tpl, {
299 singleSelect:true, store: this.store, selectedClass: this.selectedClass
302 this.view.on('click', this.onViewClick, this);
303 this.setValue(this.defaultDialCode);
306 onTriggerClick : function(e)
308 Roo.log('trigger click');
309 if(this.disabled || !this.triggerList){
313 if(this.isExpanded()){
315 this.hasFocus = false;
318 this.hasFocus = true;
323 isExpanded : function()
325 return this.list.isVisible();
328 collapse : function()
330 if(!this.isExpanded()){
334 Roo.get(document).un('mousedown', this.collapseIf, this);
335 Roo.get(document).un('mousewheel', this.collapseIf, this);
336 this.fireEvent('collapse', this);
344 if(this.isExpanded() || !this.hasFocus){
348 var lw = this.listWidth || Math.max(this.inputEl().getWidth(), this.minListWidth);
349 this.list.setWidth(lw);
352 this.restrictHeight();
354 Roo.get(document).on('mousedown', this.collapseIf, this);
355 Roo.get(document).on('mousewheel', this.collapseIf, this);
357 this.fireEvent('expand', this);
360 restrictHeight : function()
362 this.list.alignTo(this.inputEl(), this.listAlign);
363 this.list.alignTo(this.inputEl(), this.listAlign);
366 onViewOver : function(e, t)
371 var item = this.view.findItemFromChild(t);
374 var index = this.view.indexOf(item);
375 this.select(index, false);
380 onViewClick : function(view, doFocus, el, e)
382 var index = this.view.getSelectedIndexes()[0];
384 var r = this.store.getAt(index);
387 this.onSelect(r, index);
389 if(doFocus !== false && !this.blockFocus){
390 this.inputEl().focus();
394 onViewMove : function(e, t)
396 this.inKeyMode = false;
399 select : function(index, scrollIntoView)
401 this.selectedIndex = index;
402 this.view.select(index);
403 if(scrollIntoView !== false){
404 var el = this.view.getNode(index);
406 this.list.scrollChildIntoView(el, false);
411 createList : function()
413 this.list = Roo.get(document.body).createChild({
415 cls: 'typeahead typeahead-long dropdown-menu tel-list',
416 style: 'display:none'
418 this.list.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';;
421 collapseIf : function(e)
423 var in_combo = e.within(this.el);
424 var in_list = e.within(this.list);
425 var is_list = (Roo.get(e.getTarget()).id == this.list.id) ? true : false;
427 if (in_combo || in_list || is_list) {
433 onSelect : function(record, index)
435 if(this.fireEvent('beforeselect', this, record, index) !== false){
437 this.setFlagClass(record.data.iso2);
438 this.setDialCode(record.data.dialCode);
439 this.hasFocus = false;
441 this.fireEvent('select', this, record, index);
447 var flag = this.el.select('div.flag',true).first();
454 dialCodeHolderEl : function()
456 var d = this.el.select('input.dial-code-holder',true).first();
463 setDialCode : function(v)
465 this.dialCodeHolder.dom.value = '+'+v;
468 setFlagClass : function(n)
470 this.flag.dom.className = 'flag '+n;
473 getValue : function()
475 var v = this.inputEl().getValue();
476 if(this.dialCodeHolder) {
477 v = this.dialCodeHolder.dom.value+this.inputEl().getValue();
482 setValue : function(v)
484 var d = this.getDialCode(v);
487 if(v.length == 0 || !d || d.length == 0) {
489 this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
490 this.hiddenEl().dom.value = (v === null || v === undefined ? '' : v);
496 this.setFlagClass(this.dialCodeMapping[d].iso2);
498 this.inputEl().dom.value = v.replace('+'+d,'');
499 this.hiddenEl().dom.value = this.getValue();
504 getDialCode : function(v = '')
507 return this.dialCodeHolder.dom.value;
511 if (v.charAt(0) != "+") {
514 var numericChars = "";
515 for (var i = 1; i < v.length; i++) {
519 if (this.dialCodeMapping[numericChars]) {
520 dialCode = v.substr(1, i);
522 if (numericChars.length == 4) {
532 this.setValue(this.defaultDialCode);
536 hiddenEl : function()
538 return this.el.select('input.hidden-tel-input',true).first();
541 onKeyUp : function(e)
544 this.setValue(this.getValue());
547 onKeyPress : function(e){
551 var c = e.getCharCode();
554 (String.fromCharCode(c) == '.' || String.fromCharCode(c) == '-') &&
555 allowed.indexOf(String.fromCharCode(c)) === -1
561 if(!Roo.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)){
565 if(allowed.indexOf(String.fromCharCode(c)) === -1){