Skip to content

Instantly share code, notes, and snippets.

@maiordom
Created October 1, 2014 10:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maiordom/c0fabccb72fb3c81c079 to your computer and use it in GitHub Desktop.
Save maiordom/c0fabccb72fb3c81c079 to your computer and use it in GitHub Desktop.
simple refactoring №3
(function( $ ) {
'use strict';
var ElementRegion = function( $el ) {
this.cacheObjects( $el );
this.bindEvents();
};
ElementRegion.prototype = {
cacheObjects: function( $el ) {
this.$el = $el;
this.state = 'default';
this.$regions = this.$el.find( '.js-location-regions' );
this.$submit = this.$el.find( '.js-location-submit' );
this.$add = this.$el.find( '.js-location-add' );
this.$notify = this.$el.find( '.js-location-notify' );
this.$panel = this.$el.find( '.js-location-panel' );
this.$input = this.$el.find( '.js-location-input' );
this.$loader = this.$el.find( '.js-location-loader' );
this.$anotherRegion = this.$el.find( '.js-location-another-region' );
this.$currLoader = $( {} );
this.form = '.js-location-form';
},
bindEvents: function() {
this.$regions.on( 'click', '.del', _.bindEvent( this.onDeleteKladdr, this ) );
this.$anotherRegion.on( 'click', 'a', _.bindEvent( this.onAnotherRegionClick, this ) );
this.$add.on( 'click', _.bindEvent( this.onAddClick, this ) );
this.$input.enterKey( _.bindEvent( this.onEnterKey, this ) );
this.$input.focus( _.bindEvent( this.onFocus, this ) );
this.$submit.on( 'click', this.onSubmit.bind( this ) );
},
onAnotherRegionClick: function( eventContext, e ) {
if ( this.state === 'local' ) {
var $region = $( eventContext ),
kladdrName = $region.text(),
kladdrId = $region.attr( 'href' ).match( /sk=(\d+)/ )[ 1 ];
this.$el.data( 'pluginModal' ).close();
this.$regions.empty();
this.addKladdr( { id: kladdrId, label: kladdrName, parentIds: [], subDomain: '' } );
this.$notify.hide();
this.$panel.show();
AM.PubSub.pub( 'submit:regions', [ [ kladdrName ], [ kladdrId ] ] );
e.preventDefault();
}
},
onSubmit: function() {
if ( this.state === 'local' ) {
var kladdrNames = this.getKladdrNames(),
kladdrIds = this.getKladdr();
if ( !kladdrNames.length && !kladdrIds.length ) {
kladdrNames.push( 'Россия' );
kladdrIds.push( '0' );
}
AM.PubSub.pub( 'submit:regions', [ kladdrNames, kladdrIds ] );
this.$el.data( 'pluginModal' ).close();
return false;
} else {
this.submit();
}
},
setState: function( state ) {
this.state = state || null;
},
onDeleteKladdr: function( eventContext ) {
this.deleteKladdr( $( eventContext ) );
},
onAddClick: function( eventContext, e ) {
this.hideAdd();
e.preventDefault();
},
onEnterKey: function( eventContext ) {
var $target = $( eventContext ),
drop = $target.data( 'drop' );
if ( ( $target.val() == '') && ( drop ) ) {
this.$submit.trigger( 'click' );
}
if ( !drop ) {
$target.data( 'drop', true );
}
},
onFocus: function( eventContext ) {
// http://stackoverflow.com/questions/4132058/display-jquery-ui-auto-complete-list-on-focus-event
if ( $( eventContext ).autocomplete( "widget" ).is( ":visible" ) ) {
return;
}
$( eventContext ).autocomplete( "search" );
},
getKladdrQuery: function( request, response ) {
$.ajax({
url: '/int/controls/get-kladdrs-by-query/',
dataType: 'jsonp',
data: { q: request.term },
success: this.onSuccessGetKladdrQuery.bind( this, request, response )
});
},
createLoader: function( input ) {
this.$currLoader = input.closest( this.form ).find( this.$loader );
this.$currLoader.ajaxLoader( { opacity: false, valign: 'center' } );
},
onSuccessGetKladdrQuery: function( request, response, data ) {
var kladdrs = this.getKladdr(), hasparent;
this.$currLoader.ajaxLoader( { mode: 'off' } );
response(
$.map( data, function( item ) {
hasparent = false;
$.map( kladdrs, function( id ) {
if ( jQuery.inArray( '' + id + '', item.ParentIds ) > -1 ) {
hasparent = true;
}
} );
if ( (jQuery.inArray( item.CurrentId, kladdrs ) > -1 ) || hasparent ) {
return null;
} else {
return {
label: item.FullName,
value: item.FullName,
id: item.CurrentId,
parentIds: item.ParentIds,
subDomain: item.SubDomain
}
}
})
);
},
renderItem: function( ul, item ) {
var $class = ( item.parentIds.length == 0 ) ? "class='au-bold'" : "";
return $( "<li>" )
.data( "item.autocomplete", item )
.append( "<a " + $class + ">" + item.label + "</a>" )
.appendTo( ul );
},
modal: function() {
var self = this;
this.$el.modal({
center: true,
size: [ '570' ],
onOpen: function() {
self.$input.each( function() {
self.initAutocomplete( $( this ) );
$( this ).data( "autocomplete" )._renderItem = self.renderItem;
});
}
} );
},
initAutocomplete: function( $input ) {
$input.autocomplete({
appendTo: $input.closest( '.au-form-input' ),
minLength: 1,
autoFocus: true,
source: _.bindEvent( this.onSourceAutocomplete, this ),
select: _.bindEvent( this.onSelectAutocomplete, this )
});
},
onSourceAutocomplete: function( eventContext, request, response ) {
this.createLoader( eventContext.element );
this.getKladdrQuery( request, response );
},
onSelectAutocomplete: function( eventContext, event, ui ) {
var selected = $( 'input.kladdrs[value=' + ui.item.id + ']' ).length,
$el = $( eventContext );
if ( selected > 0 ) {
return false;
}
if ( $el.data( 'location' ) == 'single' ) {
this.submit( ui.item.id );
} else {
this.addKladdr( ui.item );
this.checkKladdrs();
this.changeLabel();
$el.val( '' ).data( 'drop', false );
}
return false;
},
submit: function( kladdr ) {
var kladdrs = ( typeof kladdr == 'undefined' ) ? this.getKladdr() : [ kladdr ],
$change = this.$el.find( ".js-location-changelink" ),
link = $change.data( 'domain' ) + $change.data( 'path' ),
sk = ( kladdrs.length >= 1 ) ? kladdrs.join( ',' ) + document.location.hash : 0 + document.location.hash;
this.changeAction();
this.$el.modal( 'close' );
document.location.href = ( link.indexOf( '?' ) > 0 ) ? link + '&sk=' + sk : link + '?sk=' + sk;
},
hideAdd: function() {
this.$add.hide().siblings( this.form ).show().find( this.$input ).focus();
},
showAdd: function() {
this.$add.show().siblings( this.form ).hide();
},
getKladdr: function() {
var kladdrs = [];
$( '.name', this.$regions ).not( '.child' ).siblings( 'input:hidden' ).each( function () {
kladdrs.push( $( this ).val() );
});
return kladdrs;
},
getKladdrNames: function() {
var regions = [];
$( '.name', this.$regions ).not( '.child' ).each( function() {
regions.push( $( this ).text() );
});
return regions;
},
addKladdr: function( item ) {
var $hidden = $( '<input type="hidden" class="kladdrs" value="' + item.id + '" />' ).data( 'parents', item.parentIds ).data( 'subdomain', item.subDomain ),
$span = $( '<span class="name">' + item.label + '</span>' ),
$del = $( '<span class="del">×</span>' );
var $el = $( '<li></li>' ).append( $hidden ).append( $span ).append( $del );
this.$regions.append( $el );
},
deleteKladdr: function( element ) {
element.parent().remove();
$( 'input:hidden', this.$regions ).data( 'skip', false );
if ( $( 'input:hidden', this.$regions ).length <= 1 ) {
$( '.name', this.$regions ).removeClass( 'child' );
$( '.comment', this.$regions ).remove();
} else {
this.checkKladdrs();
}
this.changeLabel();
},
checkKladdrs:function () {
var self = this;
$( 'input:hidden', self.$regions ).each( function () {
if ( $( this ).data( 'skip' ) ) return;
var $self = $( this );
$( 'input:hidden', self.$regions ).each( function () {
if ( $( this ).data( 'skip' ) ) return;
if ( $self.val() == $( this ).val() ) return;
var parents = $( this ).data( 'parents' );
if ( parents.length <= 0 ) return;
// on parent
if ( $.inArray( $self.val(), parents ) >= 0 ) {
var comment = $( '<span class="comment">выбран более крупный регион</span>' );
$( this ).siblings( '.name' ).addClass( 'child' ).parent().append( comment );
$( this ).data( 'skip', true );
} else {
$( this ).siblings( '.name' ).removeClass( 'child' ).parent().find( '.comment' ).remove();
$( this ).data( 'skip', false );
}
} );
} );
},
changeLabel: function() {
var count = $( '.name', this.$regions ).length;
this.showAdd();
if ( count > 0 ) {
this.$notify.hide();
this.$panel.show();
} else {
this.$notify.show();
this.$panel.hide();
}
this.$submit.show();
},
changeAction: function() {
var $change = this.$el.find( 'js-location-changelink', this.$elem ),
subDomain = '',
change = false;
$( 'input:hidden.kladdrs', this.$regions ).each( function() {
var regionSubDomain = $( this ).data( 'subdomain' );
if( ( subDomain == '' && regionSubDomain != '' ) || ( subDomain == regionSubDomain ) ) {
subDomain = regionSubDomain;
change = true;
} else if( subDomain != regionSubDomain ) {
change = false;
}
});
if ( false && change && subDomain != '' ) {
$change.data( 'domain', subDomain );
}
}
};
$( document ).ready( function() {
var location = new ElementRegion( $( '.js-location-modal' ) ), state;
$( '.js-top-city' ).click( function( e ) {
state = $( this ).data( 'state' );
location.setState( state );
location.modal();
e.preventDefault();
});
$( document ).on( 'click', '.js-another-city', function() {
state = $( this ).data( 'state' );
location.setState( state );
location.modal();
return false;
});
});
})( jQuery, window, undefined );
// Change location modal
// TODO - realize external plugin for region autocomplete
var modalLocations = {
$elem : $( '#js-location' )
, $regions : $( '#js-location-regions' )
, $submit : $( '#js-location-submit' )
, $add : $( '#js-location-add' )
, $block1 : $( '#js-location-block1' )
, $block2 : $( '#js-location-block2' )
, $input : $( '.js-location-input' )
, $loader : $( '.js-location-loader' )
, form : '.js-location-form'
, bindEvents: function () {
var self = this;
// delete kladdr
$( self.$regions ).on( 'click', '.del', function () {
self.deleteKladdr( $( this ) );
} );
// add region link
self.$add.click( function (e) {
self.hideAdd();
e.preventDefault();
} );
// autocomplete input field - Enter keypress
self.$input.enterKey(function (event) {
var drop = $( this ).data( 'drop' );
if ( ($( this ).val() == '') && (drop) ) { self.$submit.trigger( 'click' ); }
if ( !drop ) { $( this ).data( 'drop', true ); }
} ).focus( function () {
// refs 21693
// http://stackoverflow.com/questions/4132058/display-jquery-ui-auto-complete-list-on-focus-event
if ( $( this ).autocomplete( "widget" ).is( ":visible" ) ) {
return;
}
$( this ).autocomplete( "search" );
} );
}
, modal: function () {
var self = this;
self.$elem.modal( {
center: true,
size: ['570'],
onOpen: function(obj) {
// submit
self.$submit.one('click', function () {
self.submit();
} );
// Top menu - showing location popup window - city autocomplete
// TODO - replace by global wrapper plugin for autocomplete for region select
self.$input.each( function () {
$( this ).autocomplete( {
appendTo: $( this ).closest( '.au-form-input' )
, source:function (request, response) {
var $loader = this.element.closest( self.form ).find( self.$loader );
$loader.ajaxLoader( {'opacity': false, 'valign': 'center'} );
$.ajax( {
url : "/int/controls/get-kladdrs-by-query/",
dataType : "jsonp",
data : { q:request.term }
, success:function (data) {
var kladdrs = self.getKladdr()
, hasparent;
$loader.ajaxLoader( {'mode':'off'} );
response( $.map( data, function (item) {
hasparent = false;
$.map( kladdrs, function (id) {
if ( jQuery.inArray( '' + id + '', item.ParentIds ) > -1 ) {
hasparent = true;
}
} );
if ( (jQuery.inArray( item.CurrentId, kladdrs ) > -1) || hasparent ) {
return null;
} else {
return {
label:item.FullName,
value:item.FullName,
id:item.CurrentId,
parentIds:item.ParentIds,
subDomain:item.SubDomain
}
}
} ) );
}
} );
}
, minLength: 1
, autoFocus: true
, select:function (event, ui) {
var selected = $( 'input.kladdrs[value=' + ui.item.id + ']' ).length;
if ( selected > 0 ) {
return false;
}
if ( $( this ).data( 'location' ) == 'single' ) {
self.submit(ui.item.id);
} else {
self.addKladdr(ui.item);
self.checkKladdrs();
self.changeLabel();
$( this ).val( '' ).data( 'drop', false );
}
return false;
}
} ).data( "autocomplete" )._renderItem = function( ul, item ) {
var $class = ( item.parentIds.length == 0 ) ? "class='au-bold'" : "";
return $( "<li>" )
.data( "item.autocomplete", item )
.append( "<a " + $class + ">" + item.label + "</a>" )
.appendTo( ul );
};
} );
}
} );
}
, submit: function (kladdr) {
var kladdrs = ( typeof kladdr == 'undefined' ) ? this.getKladdr() : [kladdr]
, $change = $( "#js-location-changelink" )
, link = $change.data( 'domain' ) + $change.data( 'path' )
, sk = ( kladdrs.length >= 1 ) ? kladdrs.join( ',' ) + document.location.hash : 0 + document.location.hash;
this.changeAction();
this.$elem.modal( 'close' );
document.location.href = ( link.indexOf( '?' ) > 0 ) ? link + '&sk=' + sk : link + '?sk=' + sk;
}
, hideAdd: function () {
this.$add.hide().siblings( this.form ).show().find( this.$input ).focus();
}
, showAdd: function () {
this.$add.show().siblings( this.form ).hide();
}
, getKladdr: function () {
var kladdrs = [];
$( '.name', this.$regions ).not( '.child' ).siblings( 'input:hidden' ).each( function () {
kladdrs.push( $( this ).val() );
} );
return kladdrs;
}
, addKladdr: function (item) {
var $hidden = $( '<input type="hidden" class="kladdrs" value="' + item.id + '" />' ).data( 'parents', item.parentIds ).data( 'subdomain', item.subDomain );
var $span = $( '<span class="name">' + item.label + '</span>' )
, $del = $( '<span class="del">×</span>' );
var $li = $( '<li></li>' );
this.$regions.append( $li.append( $hidden ).append( $span ).append( $del ) );
}
, deleteKladdr: function (element) {
var self = this;
element.parent().remove();
$( 'input:hidden', self.$regions ).data( 'skip', false );
if ( $( 'input:hidden', self.$regions ).length <= 1 ) {
$( '.name', self.$regions ).removeClass( 'child' );
$( '.comment', self.$regions ).remove();
} else {
self.checkKladdrs();
}
self.changeLabel();
}
, checkKladdrs:function () {
var self = this;
$( 'input:hidden', self.$regions ).each( function () {
if ( $( this ).data( 'skip' ) ) return;
var $self = $( this );
$( 'input:hidden', self.$regions ).each( function () {
if ( $( this ).data( 'skip' ) ) return;
if ( $self.val() == $( this ).val() ) return;
var parents = $( this ).data( 'parents' );
if ( parents.length <= 0 ) return;
// on parent
if ( $.inArray( $self.val(), parents ) >= 0 ) {
var comment = $( '<span class="comment">выбран более крупный регион</span>' );
$( this ).siblings( '.name' ).addClass( 'child' ).parent().append( comment );
$( this ).data( 'skip', true );
} else {
$( this ).siblings( '.name' ).removeClass( 'child' ).parent().find( '.comment' ).remove();
$( this ).data( 'skip', false );
}
} );
} );
}
, changeLabel:function () {
var count = $( '.name', this.$regions ).length;
this.showAdd();
if ( count > 0 ) {
this.$block1.hide();
this.$block2.show();
} else {
this.$block1.show();
this.$block2.hide();
}
this.$submit.show();
}
, changeAction:function () {
var $change = $( "#js-location-changelink", this.$elem )
, subDomain = ''
, change = false;
$( 'input:hidden.kladdrs', self.$regions ).each( function () {
var regionSubDomain = $( this ).data( 'subdomain' );
if( ( subDomain == '' && regionSubDomain != '' ) || ( subDomain == regionSubDomain ) ) {
subDomain = regionSubDomain;
change = true;
} else if( subDomain != regionSubDomain ) {
change = false;
}
} );
if( false && change && subDomain != '' ) {
$change.data( 'domain', subDomain ) ;
}
}
};
modalLocations.bindEvents();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment