jQuery Object Method Gets Called Multiple Times - javascript

I am trying to write a jQuery method which watches for changes of inputs inside a given form element:
(function($) {
$.fn.filter = function(options) {
console.log('Outside');
var self = this;
var settings = $.extend({}, options);
this.on('change', ':input', function(e) {
console.log('Inside');
$(self).serialize(); // Here is the problem
});
return this;
}
})(jQuery);
$('#filter-form').filter();
When I use $(self).serialize();, the function being called again. I expect that the 'Outside' part only runs once on initialization and not every time the input of the form changes.
I do not understand what is happening here. I'd appreciate if someone could explain to me why this is happening!

The issue is that you are redefining jQuery's filter method, which it internally uses in its serialize method. If you change the name, it will work. The definition of serialize is shown below:
jQuery.fn.extend( {
serialize: function() {
return jQuery.param( this.serializeArray() );
},
serializeArray: function() {
return this.map( function() {
// Can add propHook for "elements" to filter or add form elements
var elements = jQuery.prop( this, "elements" );
return elements ? jQuery.makeArray( elements ) : this;
} )
.filter( function() {
var type = this.type;
// Use .is( ":disabled" ) so that fieldset[disabled] works
return this.name && !jQuery( this ).is( ":disabled" ) &&
rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
( this.checked || !rcheckableType.test( type ) );
} )
.map( function( _i, elem ) {
var val = jQuery( this ).val();
if ( val == null ) {
return null;
}
if ( Array.isArray( val ) ) {
return jQuery.map( val, function( val ) {
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
} );
}
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
} ).get();
}
} );
Working Example:
(function($) {
$.fn._filter = function(options) {
console.log('Outside');
var self = this;
var settings = $.extend({}, options);
this.on('change', ':input', function(e) {
console.log('Inside');
$(self).serialize();
});
return this;
}
})(jQuery);
$('#filter-form')._filter();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="filter-form">
<input type="text">
</form>

Related

Javascript initialize events from variable

i have plugin construction like this:
(function($){
var defaults = {
param1:null,
param2:null
};
var methods = {
init:function(params) {
var options = $.extend({}, defaults, params);
$(this).append('<button class="addbtn">Add elements</button>');
$(document).on('click','.addbtn',function(){
$('body').append(button.html+input.html);
});
}
};
var button = {
html: '<button class="btn">Button</button>'
};
var input = {
html: '<input type="text" class="input" value="" />'
};
var actions ={
clicked:function(){
alert('clicked');
},
hover:function(){
alert('hover');
}
};
$.fn.JPlugin = function(method){
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method"' + method + '" is not found jQuery.mySimplePlugin' );
}
};
})(jQuery);
$('body').JPlugin();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
By clicking on add button you will add input from input.html and button from button.html. How can i initialize click event for input element and button objects from actions.clicked and hover event from actions.hover
You can define events when append button and input.Try following code i hope this helpful.
(function($){
var defaults = {
param1:null,
param2:null
};
var methods = {
init:function(params) {
var options = $.extend({}, defaults, params);
$(this).append('<button class="addbtn">Add elements</button>');
$(document).on('click','.addbtn',function(){
$('body').append(button.html+input.html)
.find(".foo")
.click(function(){actions.clicked($(this))})
.hover(function(){actions.hover($(this))})
});
}
};
var button = {
html: '<button class="btn foo">Button</button>'
};
var input = {
html: '<input type="text" class="input foo" value="" />'
};
var actions ={
clicked:function($this){
console.log($this);
},
hover:function($this){
console.log($this);
}
};
$.fn.JPlugin = function(method){
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method"' + method + '" is not found jQuery.mySimplePlugin' );
}
};
})(jQuery);
$('body').JPlugin();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Ionic - when should ionicModal.remove() be called? [Ionic Modal Hide Callback]

In my controller, modal views are initialized with a factory by listening to the $ionicView.afterEnter event. As the documentation suggests, modal views should be removed whenever the current active ionic view is about to be destroyed. A function is called in the $ionicView.beforeLeave callback in order to remove the modal views.
.controller('UserProfileCtrl', function($scope, $state, user, ModalFactory) {
$scope.user = user;
$scope.checkOrders = function() {
$state.go('app.orders');
};
$scope.$on('$ionicView.afterEnter', function() {
$scope.modals = ModalFactory.getUserProfileModals($scope, user.photos);
});
$scope.$on('$ionicView.beforeLeave', function() {
$scope.modals.remove();
});
});
.factory('ModalFactory', function($ionicModal, $ionicSlideBoxDelegate) {
var modalFactory = {};
modalFactory.getUserProfileModals = function(scope, images) {
var modals = {
'views': [],
'data': []
};
$ionicModal.fromTemplateUrl('templates/modals/common/image-view.html', { 'scope': scope }).then(function(modal) { modals.views.imageView = modal; });
if (images) {
modals.data.images = images;
}
modals.open = function(view, slide) {
Object.keys(this.views).forEach(function(key, index) {
console.log(key);
});
if (view && this.views.hasOwnProperty(view)) {
this.views[view].show();
if (view == 'imageView' && slide) {
$ionicSlideBoxDelegate.$getByHandle('image-view').slide(slide);
}
}
};
modals.close = function(view) {
Object.keys(this.views).forEach(function(key, index) {
console.log(key);
});
if (view && this.views.hasOwnProperty(view)) {
this.views[view].hide();
} else {
Object.keys(this.views).forEach(function(key, index) {
this.views[key].hide();
});
}
};
modals.remove = function() {
console.log('remove');
Object.keys(this.views).forEach(function(key, index) {
console.log(key);
});
this.data.splice(0, this.data.length);
Object.keys(this.views).forEach(function(key, index) {
this.views[key].remove();
});
this.views.splice(0, this.views.length);
};
return modals;
};
return modalFactory;
});
However, I get the following output in the console when I execute these actions in sequence:
call $scope.modals.open('imageView', 1),
call $scope.modals.close(),
navigate to another page with $state.go('app.orders').
I tried listening to $destroy instead of $ionicView.beforeLeave, but then $scope.modals.remove() is not called at all. It seems $destroy is not fired when I am testing my application with Chrome.
Can anyone tell me when should I remove the modal views, and why is there such an error message in my scenario?
Update
After I modified the code in ModalFactory as follows, the error is gone.
function open(view, slide) {
if (view && modals.views.hasOwnProperty(view)) {
modals.views[view].show();
if (view == 'imageView' && slide) {
$ionicSlideBoxDelegate.$getByHandle('image-view').slide(slide);
}
}
};
function close(view) {
if (view && modals.views.hasOwnProperty(view)) {
modals.views[view].hide();
} else {
Object.keys(modals.views).forEach(function(key, index) {
modals.views[key].hide();
});
}
};
function remove() {
console.log('remove');
modals.data.splice(0, modals.data.length);
Object.keys(modals.views).forEach(function(key, index) {
modals.views[key].remove();
});
modals.views.splice(0, modals.views.length);
};
modals.open = open;
modals.close = close;
modals.remove = remove;
return modals;
By using $scope.$on('$destroy', ..) method Angular will broadcast a $destroy event just before tearing down a scope and removing the scope from its parent.
Here is the example of how i resolved modal.remove() issue,
.factory('ModalFactory', function($ionicModal, $rootScope) {
var init = function(tpl, $scope) {
var promise;
$scope = $scope || $rootScope.$new();
promise = $ionicModal.fromTemplateUrl(tpl, {
scope: $scope,
animation: 'slide-in-right'
}).then(function(modal) {
$scope.modal = modal;
return modal;
});
$scope.openModal = function() {
$scope.modal.show();
};
$scope.closeModal = function() {
$scope.modal.hide();
};
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
return promise;
};
return {
init: init
}
})
And from the controller, pass the current scope of controller and modal template
.controller('UserProfileCtrl', function($scope, $state, user, ModalFactory) {
ModalFactory.init('image-view.html', $scope)
.then(function(modal) {
confirmationModal = modal;
confirmationModal.show();
});
})
Hope this is helpful for you.
As I was looking for a solution in 2016, it is mentioned that
$scope.$on('destroy') isn't called in new ionic builds where cache is
used
so I came up with a solution to add event listener for animation/transition end on modal.hidden.
First of all this solution solves the animation end event problem.
The awesome guy made two libraries, one with jQuery Depency, and the other is written in plain javascript.
jQuery Plugin:
/*
By Osvaldas Valutis, www.osvaldas.info
Available for use under the MIT License
*/
;( function( $, window, document, undefined )
{
var s = document.body || document.documentElement, s = s.style, prefixAnimation = '', prefixTransition = '';
if( s.WebkitAnimation == '' ) prefixAnimation = '-webkit-';
if( s.MozAnimation == '' ) prefixAnimation = '-moz-';
if( s.OAnimation == '' ) prefixAnimation = '-o-';
if( s.WebkitTransition == '' ) prefixTransition = '-webkit-';
if( s.MozTransition == '' ) prefixTransition = '-moz-';
if( s.OTransition == '' ) prefixTransition = '-o-';
$.fn.extend(
{
onCSSAnimationEnd: function( callback )
{
var $this = $( this ).eq( 0 );
$this.one( 'webkitAnimationEnd mozAnimationEnd oAnimationEnd oanimationend animationend', callback );
if( ( prefixAnimation == '' && !( 'animation' in s ) ) || $this.css( prefixAnimation + 'animation-duration' ) == '0s' ) callback();
return this;
},
onCSSTransitionEnd: function( callback )
{
var $this = $( this ).eq( 0 );
$this.one( 'webkitTransitionEnd mozTransitionEnd oTransitionEnd otransitionend transitionend', callback );
if( ( prefixTransition == '' && !( 'transition' in s ) ) || $this.css( prefixTransition + 'transition-duration' ) == '0s' ) callback();
return this;
}
});
})( jQuery, window, document );
or use
Plain Javascript Library:
/*
By Osvaldas Valutis, www.osvaldas.info
Available for use under the MIT License
*/
;( function ( document, window, index )
{
var s = document.body || document.documentElement, s = s.style, prefixAnimation = '', prefixTransition = '';
if( s.WebkitAnimation == '' ) prefixAnimation = '-webkit-';
if( s.MozAnimation == '' ) prefixAnimation = '-moz-';
if( s.OAnimation == '' ) prefixAnimation = '-o-';
if( s.WebkitTransition == '' ) prefixTransition = '-webkit-';
if( s.MozTransition == '' ) prefixTransition = '-moz-';
if( s.OTransition == '' ) prefixTransition = '-o-';
Object.prototype.onCSSAnimationEnd = function( callback )
{
var runOnce = function( e ){ callback(); e.target.removeEventListener( e.type, runOnce ); };
this.addEventListener( 'webkitAnimationEnd', runOnce );
this.addEventListener( 'mozAnimationEnd', runOnce );
this.addEventListener( 'oAnimationEnd', runOnce );
this.addEventListener( 'oanimationend', runOnce );
this.addEventListener( 'animationend', runOnce );
if( ( prefixAnimation == '' && !( 'animation' in s ) ) || getComputedStyle( this )[ prefixAnimation + 'animation-duration' ] == '0s' ) callback();
return this;
};
Object.prototype.onCSSTransitionEnd = function( callback )
{
var runOnce = function( e ){ callback(); e.target.removeEventListener( e.type, runOnce ); };
this.addEventListener( 'webkitTransitionEnd', runOnce );
this.addEventListener( 'mozTransitionEnd', runOnce );
this.addEventListener( 'oTransitionEnd', runOnce );
this.addEventListener( 'transitionend', runOnce );
this.addEventListener( 'transitionend', runOnce );
if( ( prefixTransition == '' && !( 'transition' in s ) ) || getComputedStyle( this )[ prefixTransition + 'transition-duration' ] == '0s' ) callback();
return this;
};
}( document, window, 0 ));
Next in your Ionic Code, listen to Modal Hide Event:
$scope.$on('modal.hidden', function() {
$( '.modal' ).onCSSAnimationEnd( function()//this example uses jQuery Plugin
{
$scope.modal.remove();
});
});
Or Plain Javascripy Example:
var item = document.querySelector( '.modal' );
item.onCSSAnimationEnd( function()
{
$scope.modal.remove();
});
Hope it helps someone someday.

Call Javascript Function from URL

The javascript below enables swipe left/right navigation. For some reason, I would like to call this function using URL such as <a href="javascript:function">. Certain URL will equivalent to left swipe, while another URL will equivalent to right swipe. Is this possible?
(function( window ){
var window = window,
document = window.document,
screen = window.screen,
touchSwipeListener = function( options ) {
// Private members
var track = {
startX: 0,
endX: 0
},
defaultOptions = {
moveHandler: function( direction ) {},
endHandler: function( direction ) {},
minLengthRatio: 0.3
},
getDirection = function() {
return track.endX > track.startX ? "prev" : "next";
},
isDeliberateMove = function() {
var minLength = Math.ceil( screen.width * options.minLengthRatio );
return Math.abs(track.endX - track.startX) > minLength;
},
extendOptions = function() {
for (var prop in defaultOptions) {
if ( defaultOptions.hasOwnProperty( prop ) ) {
options[ prop ] || ( options[ prop ] = defaultOptions[ prop ] );
}
}
},
handler = {
touchStart: function( event ) {
// At least one finger has touched the screen
if ( event.touches.length > 0 ) {
track.startX = event.touches[0].pageX;
}
},
touchMove: function( event ) {
if ( event.touches.length > 0 ) {
track.endX = event.touches[0].pageX;
options.moveHandler( getDirection(), isDeliberateMove() );
}
},
touchEnd: function( event ) {
var touches = event.changedTouches || event.touches;
if ( touches.length > 0 ) {
track.endX = touches[0].pageX;
isDeliberateMove() && options.endHandler( getDirection() );
}
}
};
extendOptions();
// Graceful degradation
if ( !document.addEventListener ) {
return {
on: function() {},
off: function() {}
}
}
return {
on: function() {
document.addEventListener('touchstart', handler.touchStart, false);
document.addEventListener('touchmove', handler.touchMove, false);
document.addEventListener('touchend', handler.touchEnd, false);
},
off: function() {
document.removeEventListener('touchstart', handler.touchStart);
document.removeEventListener('touchmove', handler.touchMove);
document.removeEventListener('touchend', handler.touchEnd);
}
}
}
// Expose global
window.touchSwipeListener = touchSwipeListener;
}( window ));
(function( window ){
var document = window.document,
// Element helpers
Util = {
addClass: function( el, className ) {
el.className += " " + className;
},
hasClass: function( el, className ) {
var re = new RegExp("\s?" + className, "gi");
return re.test( el.className );
},
removeClass: function( el, className ) {
var re = new RegExp("\s?" + className, "gi");
el.className = el.className.replace(re, "");
}
},
swipePageNav = (function() {
// Page sibling links like <link rel="prev" title=".." href=".." />
// See also http://diveintohtml5.info/semantics.html
var elLink = {
prev: null,
next: null
},
// Arrows, which slide in to indicate the shift direction
elArrow = {
prev: null,
next: null
},
swipeListener;
return {
init: function() {
this.retrievePageSiblings();
// Swipe navigation makes sense only if any of sibling page link available
if ( !elLink.prev && !elLink.next ) {
return;
}
this.renderArows();
this.syncUI();
},
syncUI: function() {
var that = this;
// Assign handlers for swipe "in progress" / "complete" events
swipeListener = new window.touchSwipeListener({
moveHandler: function( direction, isDeliberateMove ) {
if ( isDeliberateMove ) {
if ( elArrow[ direction ] && elLink[ direction ] ) {
Util.hasClass( elArrow[ direction ], "visible" ) ||
Util.addClass( elArrow[ direction ], "visible" );
}
} else {
Util.removeClass( elArrow.next, "visible" );
Util.removeClass( elArrow.prev, "visible" );
}
},
endHandler: function( direction ) {
that[ direction ] && that[ direction ]();
}
});
swipeListener.on();
},
retrievePageSiblings: function() {
elLink.prev = document.querySelector( "head > link[rel=prev]");
elLink.next = document.querySelector( "head > link[rel=next]");
},
renderArows: function() {
var renderArrow = function( direction ) {
var div = document.createElement("div");
div.className = "spn-direction-sign " + direction;
document.getElementsByTagName( "body" )[ 0 ].appendChild( div );
return div;
}
elArrow.next = renderArrow( "next" );
elArrow.prev = renderArrow( "prev" );
},
// When the shift (page swap) is requested, this overlay indicates that
// the current page is frozen and a new one is loading
showLoadingScreen: function() {
var div = document.createElement("div");
div.className = "spn-freezing-overlay";
document.getElementsByTagName( "body" )[ 0 ].appendChild( div );
},
// Request the previous sibling page
prev: function() {
if ( elLink.prev ) {
this.showLoadingScreen();
window.location.href = elLink.prev.href;
}
},
// Request the next sibling page
next: function() {
if ( elLink.next ) {
this.showLoadingScreen();
window.location.href = elLink.next.href;
}
}
}
}())
// Apply when document is ready
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
try {
swipePageNav.init();
} catch (e) {
alert(e);
}
}, false );
}( window ));
You cannot do that. However, if it is for organization goals why not have two JavaScript files, each one with its own namespace. If you do this, you call only that namespace expected for the link clicked.

Responsive Multi-Level Menu - How to close menu when link is clicked?

I have a very simple menu, no sub menus and was curious how I would get the menu to close when I click on one of the links?
Plugin Home Page ->
Here is the code directly out of the .js file that comes in the zip when you download this menu. I really need to know what code to add and where to add it so that when I click a link it closes the menu.
;( function( $, window, undefined ) {
'use strict';
// global
var Modernizr = window.Modernizr, $body = $( 'body' );
$.DLMenu = function( options, element ) {
this.$el = $( element );
this._init( options );
};
// the options
$.DLMenu.defaults = {
// classes for the animation effects
animationClasses : { classin : 'dl-animate-in-1', classout : 'dl-animate-out-1' },
// callback: click a link that has a sub menu
// el is the link element (li); name is the level name
onLevelClick : function( el, name ) { return false; },
// callback: click a link that does not have a sub menu
// el is the link element (li); ev is the event obj
onLinkClick : function( el, ev ) { return false; }
};
$.DLMenu.prototype = {
_init : function( options ) {
// options
this.options = $.extend( true, {}, $.DLMenu.defaults, options );
// cache some elements and initialize some variables
this._config();
var animEndEventNames = {
'WebkitAnimation' : 'webkitAnimationEnd',
'OAnimation' : 'oAnimationEnd',
'msAnimation' : 'MSAnimationEnd',
'animation' : 'animationend'
},
transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd',
'msTransition' : 'MSTransitionEnd',
'transition' : 'transitionend'
};
// animation end event name
this.animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ] + '.dlmenu';
// transition end event name
this.transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ] + '.dlmenu',
// support for css animations and css transitions
this.supportAnimations = Modernizr.cssanimations,
this.supportTransitions = Modernizr.csstransitions;
this._initEvents();
},
_config : function() {
this.open = false;
this.$trigger = this.$el.children( '.dl-trigger' );
this.$menu = this.$el.children( 'ul.dl-menu' );
this.$menuitems = this.$menu.find( 'li:not(.dl-back)' );
this.$el.find( 'ul.dl-submenu' ).prepend( '<li class="dl-back">BACK</li>' );
this.$back = this.$menu.find( 'li.dl-back' );
},
_initEvents : function() {
var self = this;
this.$trigger.on( 'click.dlmenu', function() {
if( self.open ) {
self._closeMenu();
}
else {
self._openMenu();
}
return false;
} );
this.$menuitems.on( 'click.dlmenu', function( event ) {
event.stopPropagation();
var $item = $(this),
$submenu = $item.children( 'ul.dl-submenu' );
if( $submenu.length > 0 ) {
var $flyin = $submenu.clone().css( 'opacity', 0 ).insertAfter( self.$menu ),
onAnimationEndFn = function() {
self.$menu.off( self.animEndEventName ).removeClass( self.options.animationClasses.classout ).addClass( 'dl-subview' );
$item.addClass( 'dl-subviewopen' ).parents( '.dl-subviewopen:first' ).removeClass( 'dl-subviewopen' ).addClass( 'dl-subview' );
$flyin.remove();
};
setTimeout( function() {
$flyin.addClass( self.options.animationClasses.classin );
self.$menu.addClass( self.options.animationClasses.classout );
if( self.supportAnimations ) {
self.$menu.on( self.animEndEventName, onAnimationEndFn );
}
else {
onAnimationEndFn.call();
}
self.options.onLevelClick( $item, $item.children( 'a:first' ).text() );
} );
return false;
}
var link = $item.find('a').attr('href');
var hash = link.substring(link.indexOf('#')+1);
if( hash != "" ){
var elem = jQuery('div[data-anchor="'+hash+'"]');
autoScroll(elem);
self._closeMenu();
}else{
self.options.onLinkClick( $item, event );
}
} );
this.$back.on( 'click.dlmenu', function( event ) {
var $this = $( this ),
$submenu = $this.parents( 'ul.dl-submenu:first' ),
$item = $submenu.parent(),
$flyin = $submenu.clone().insertAfter( self.$menu );
var onAnimationEndFn = function() {
self.$menu.off( self.animEndEventName ).removeClass( self.options.animationClasses.classin );
$flyin.remove();
};
setTimeout( function() {
$flyin.addClass( self.options.animationClasses.classout );
self.$menu.addClass( self.options.animationClasses.classin );
if( self.supportAnimations ) {
self.$menu.on( self.animEndEventName, onAnimationEndFn );
}
else {
onAnimationEndFn.call();
}
$item.removeClass( 'dl-subviewopen' );
var $subview = $this.parents( '.dl-subview:first' );
if( $subview.is( 'li' ) ) {
$subview.addClass( 'dl-subviewopen' );
}
$subview.removeClass( 'dl-subview' );
} );
return false;
} );
},
closeMenu : function() {
if( this.open ) {
this._closeMenu();
}
},
_closeMenu : function() {
var self = this,
onTransitionEndFn = function() {
self.$menu.off( self.transEndEventName );
self._resetMenu();
};
this.$menu.removeClass( 'dl-menuopen' );
this.$menu.addClass( 'dl-menu-toggle' );
this.$trigger.removeClass( 'dl-active' );
if( this.supportTransitions ) {
this.$menu.on( this.transEndEventName, onTransitionEndFn );
}
else {
onTransitionEndFn.call();
}
this.open = false;
},
openMenu : function() {
if( !this.open ) {
this._openMenu();
}
},
_openMenu : function() {
var self = this;
// clicking somewhere else makes the menu close
$body.off( 'click' ).on( 'click.dlmenu', function() {
self._closeMenu() ;
} );
this.$menu.addClass( 'dl-menuopen dl-menu-toggle' ).on( this.transEndEventName, function() {
$( this ).removeClass( 'dl-menu-toggle' );
} );
this.$trigger.addClass( 'dl-active' );
this.open = true;
},
// resets the menu to its original state (first level of options)
_resetMenu : function() {
this.$menu.removeClass( 'dl-subview' );
this.$menuitems.removeClass( 'dl-subview dl-subviewopen' );
}
};
var logError = function( message ) {
if ( window.console ) {
window.console.error( message );
}
};
$.fn.dlmenu = function( options ) {
if ( typeof options === 'string' ) {
var args = Array.prototype.slice.call( arguments, 1 );
this.each(function() {
var instance = $.data( this, 'dlmenu' );
if ( !instance ) {
logError( "cannot call methods on dlmenu prior to initialization; " +
"attempted to call method '" + options + "'" );
return;
}
if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
logError( "no such method '" + options + "' for dlmenu instance" );
return;
}
instance[ options ].apply( instance, args );
});
}
else {
this.each(function() {
var instance = $.data( this, 'dlmenu' );
if ( instance ) {
instance._init();
}
else {
instance = $.data( this, 'dlmenu', new $.DLMenu( options, this ) );
}
});
}
return this;
};
} )( jQuery, window );
After looking at their demo, it seems you can call method plugins. Replace dl-menu with the id of your menu.
$('#dl-menu a').click(function(e) {
$('#dl-menu').dlmenu('closeMenu');
});

jQuery combining 2 bind functions (TypeError: a is undefined)

Please give me a piece of advice.
I'm trying to write a function from 2 similar functions by combining its common parts.
From these 2 functions, I'd like to get "selected1" & "selected2", and use these value in the next function, calc.
var selected;
var selected1;
var selected2;
$( '.type1' ).bind('change', function () {
var values = [];
$( 'input.type1:checkbox:checked' ).each(function ( _, el ) {
values.push( base64decode( $( el ).data( 'val' ) ) );
if ( values.length > 1 ) {
values[0] = $.map(values[0], function (val, i) {
return values[0][i] | values[1][i];
});
values.splice(1,1);
}
});
selected1 = result;
calc();
});
$( '.type2' ).bind('change', function () {
var values = [];
$( 'input.type2:checkbox:checked' ).each(function ( _, el ) {
values.push( base64decode( $( el ).data( 'val' ) ) );
if ( values.length > 1 ) {
values[0] = $.map(values[0], function (val, i) {
return values[0][i] | values[1][i];
});
values.splice(1,1);
}
});
selected2 = result;
calc();
});
function calc () {
var selected3 = $.map(selected1, function (val, i) {
return selected1[i] & selected2[i];
});
selected = base64encode( selected3 );
overlays();
};
When I write as above, both selected1&2 are defined as global variables, so function calc works.
However, it doesn't work on my rewrite code. The firebug says "TypeError: a is undefined".
Here is my code:
function tab (checkedTab, selected) {
var values = [];
checkedTab.each(function ( _, el ) {
values.push( base64decode ($( el ).data( 'val' ) ) );
if ( values.length > 1 ) {
values[0] = $.map(values[0], function (val, i) {
return values[0][i] | values[1][i];
});
values.splice(1,1);
}
});
selected = values[0];
};
$( '.type1' ).bind('change', function () {
tab ($( 'input.type1:checkbox:checked' ), 'selected1');
calc();
});
$( '.type2' ).bind('change', function () {
tab ($( 'input.type2:checkbox:checked' ), 'selected2');
calc();
});
Could someone please tell me why my code doesn't work?
Thank you very much for your comments, Peter.
After debugging variables, it finally works!
This may not be the best way, but I will post my rewrite code as reference.
var values;
function tab (checkedTab) {
values = [];
checkedTab.each(function ( _, el ) {
values.push( base64decode ($( el ).data( 'val' ) ) );
if ( values.length > 1 ) {
values[0] = $.map(values[0], function (val, i) {
return values[0][i] | values[1][i];
});
values.splice(1,1);
}
});
return values[0];
};
$( '.type1' ).bind('change', function () {
selected1 = tab ($( 'input.type1:checkbox:checked' ));
calc();
});
$( '.type2' ).bind('change', function () {
selected2 = tab ($( 'input.type2:checkbox:checked' ));
calc();
});

Categories