jquery - Trigger method defined in javascript object, but outside of the object itself -
i suspect question may bit obtuse, , apologize. here trying achieve:
i using multi-level push menu, , works fine out of box. however, multi-level menu close after modal submitted , closed. having difficult time figuring out how trigger menu close.
so, on code. first, javascript runs menu itself.
mlpushmenu.prototype = { defaults : { // overlap: there gap between open levels // cover: open levels on top of previous open level type : 'overlap', // overlap || cover // space between each overlaped level levelspacing : 40, // classname element (if any) when clicked closes current level backclass : 'mp-back' }, _init : function() { // if menu open or not this.open = false; // level depth this.level = 0; // moving wrapper this.wrapper = document.getelementbyid( 'mp-pusher' ); // mp-level elements this.levels = array.prototype.slice.call( this.el.queryselectorall( 'div.mp-level' ) ); // save depth of each of these mp-level elements var self = this; this.levels.foreach( function( el, ) { el.setattribute( 'data-level', getleveldepth( el, self.el.id, 'mp-level' ) ); } ); // menu items this.menuitems = array.prototype.slice.call( this.el.queryselectorall( 'li' ) ); // if type == "cover" these serve hooks move previous level this.levelback = array.prototype.slice.call( this.el.queryselectorall( '.' + this.options.backclass ) ); // event type (if mobile use touch events) this.eventtype = mobilecheck() ? 'touchstart' : 'click'; // add class mp-overlap or mp-cover main element depending on options.type classie.add( this.el, 'mp-' + this.options.type ); // initialize / bind necessary events this._initevents(); }, _initevents : function() { var self = this; // menu should close if clicking somewhere on body var bodyclickfn = function( el ) { self._resetmenu(); el.removeeventlistener( self.eventtype, bodyclickfn ); }; // open (or close) menu this.trigger.addeventlistener( this.eventtype, function( ev ) { ev.stoppropagation(); ev.preventdefault(); if( self.open ) { self._resetmenu(); } else { self._openmenu(); // menu should close if clicking somewhere on body (excluding clicks on menu) document.addeventlistener( self.eventtype, function( ev ) { if( self.open && !hasparent( ev.target, self.el.id ) ) { bodyclickfn( ); } } ); } } ); // opening sub level menu this.menuitems.foreach( function( el, ) { // check if has sub level var sublevel = el.queryselector( 'div.mp-level' ); if( sublevel ) { el.queryselector( 'a' ).addeventlistener( self.eventtype, function( ev ) { ev.preventdefault(); var level = closest( el, 'mp-level' ).getattribute( 'data-level' ); if( self.level <= level ) { ev.stoppropagation(); classie.add( closest( el, 'mp-level' ), 'mp-level-overlay' ); self._openmenu( sublevel ); } } ); } } ); // closing sub levels : // clicking on visible part of level element this.levels.foreach( function( el, ) { el.addeventlistener( self.eventtype, function( ev ) { ev.stoppropagation(); var level = el.getattribute( 'data-level' ); if( self.level > level ) { self.level = level; self._closemenu(); } } ); } ); // clicking on specific element this.levelback.foreach( function( el, ) { el.addeventlistener( self.eventtype, function( ev ) { ev.preventdefault(); var level = closest( el, 'mp-level' ).getattribute( 'data-level' ); if( self.level <= level ) { ev.stoppropagation(); self.level = closest( el, 'mp-level' ).getattribute( 'data-level' ) - 1; self.level === 0 ? self._resetmenu() : self._closemenu(); } } ); } ); }, _openmenu : function( sublevel ) { // increment level depth ++this.level; // move main wrapper var levelfactor = ( this.level - 1 ) * this.options.levelspacing, translateval = this.options.type === 'overlap' ? this.el.offsetwidth + levelfactor : this.el.offsetwidth; this._settransform( 'translate3d(' + translateval + 'px,0,0)' ); if( sublevel ) { // reset transform sublevel this._settransform( '', sublevel ); // need reset translate value level menus have same level depth , not open for( var = 0, len = this.levels.length; < len; ++i ) { var levelel = this.levels[i]; if( levelel != sublevel && !classie.has( levelel, 'mp-level-open' ) ) { this._settransform( 'translate3d(-100%,0,0) translate3d(' + -1*levelfactor + 'px,0,0)', levelel ); } } } // add class mp-pushed main wrapper if opening first time if( this.level === 1 ) { classie.add( this.wrapper, 'mp-pushed' ); this.open = true; } // add class mp-level-open opening level element classie.add( sublevel || this.levels[0], 'mp-level-open' ); }, // close menu _resetmenu : function() { this._settransform('translate3d(0,0,0)'); this.level = 0; // remove class mp-pushed main wrapper classie.remove( this.wrapper, 'mp-pushed' ); this._togglelevels(); this.open = false; }, // close sub menus _closemenu : function() { var translateval = this.options.type === 'overlap' ? this.el.offsetwidth + ( this.level - 1 ) * this.options.levelspacing : this.el.offsetwidth; this._settransform( 'translate3d(' + translateval + 'px,0,0)' ); this._togglelevels(); }, // translate el _settransform : function( val, el ) { el = el || this.wrapper; el.style.webkittransform = val; el.style.moztransform = val; el.style.transform = val; }, // removes classes mp-level-open closing levels _togglelevels : function() { for( var = 0, len = this.levels.length; < len; ++i ) { var levelel = this.levels[i]; if( levelel.getattribute( 'data-level' ) >= this.level + 1 ) { classie.remove( levelel, 'mp-level-open' ); classie.remove( levelel, 'mp-level-overlay' ); } else if( number( levelel.getattribute( 'data-level' ) ) == this.level ) { classie.remove( levelel, 'mp-level-overlay' ); } } } } the method invoke _resetmenu. have tried couple of ways. primary trying trigger click event of button opens menu:
<a href="#" id="trigger" class="show-root-menu"><i class="fa fa-reorder"></i></a> however:
$('#trigger').trigger('click'); does not work expected. expect fired:
// open (or close) menu this.trigger.addeventlistener( this.eventtype, function( ev ) { ev.stoppropagation(); ev.preventdefault(); if( self.open ) { self._resetmenu(); } else { self._openmenu(); // menu should close if clicking somewhere on body (excluding clicks on menu) document.addeventlistener( self.eventtype, function( ev ) { if( self.open && !hasparent( ev.target, self.el.id ) ) { bodyclickfn( ); } } ); } } ); in case, this.eventtype 'click'.
i suspect may have how functionality coded object. while have decent javascript skills, have not had exposure using in manner.
i instantiating menu thusly:
new mlpushmenu(document.getelementbyid('mp-menu'), document.getelementbyid('trigger')); i realize extract method, seems violate best practices in general.
any suggestions appreciated!
you can't use module as-is this. event types supports "click" , "touchstart" , mobilecheck() method determines 1 of 2 uses.
you'll either have fake click on trigger element or you'll have modify module. can .click() method of dom element. .trigger.click() won't it; better off getting element (via $('#trigger') or document.getelementbyid()) , calling .click() method of that.
i tried in chrome <a> style display:none , followed link may work hidden element set trigger. it's hacky might preferable changing module.
Comments
Post a Comment