Invoking jQuery toggle method inside object literal - javascript

I'm struggling to get the below piece of code working. The problem is that when I wrap the two functions in the editItems property inside the parenthesis (), the code behaves strangely and assigns display: none inline css property to the edit button.
If I don't wrap the two functions inside the parenthesis, I get a javascript syntax error function statement requires a name.
var shoppingList = {
// Some code ...
'init' : function() {
// Capture toggle event on Edit Items button
(shoppingList.$editButton).toggle(shoppingList.editItems);
},
'editItems' : function() {
(function() {
$(this).attr('value', 'Finish editing');
(shoppingList.$ingrLinks).unbind('click', shoppingList.ingredients) // disable highlighting items
.removeAttr('href');
$('.editme').editable("enable");
$('.editme').editable('http://localhost:8000/edit-ingredient/', {
indicator : 'Saving...',
tooltip : 'Click to edit...',
submit : 'OK',
cancel : 'Cancel'
});
}), (function() {
$(this).attr('value', 'Edit item');
(shoppingList.$ingrLinks).attr('href', '#');
$('.editme').editable("disable");
(shoppingList.$ingrLinks).bind('click', shoppingList.ingredients) // re-enable highlighting items
})
}
}
$(document).ready(shoppingList.init);
However, if I invoke the toggle event "directly" like this, it works:
var shoppingList = {
// Some code ...
'init' : function() {
// Toggle event on Edit Items button
(shoppingList.$editButton).toggle(
function() {
$(this).attr('value', 'Finish editing');
(shoppingList.$ingrLinks).unbind('click', shoppingList.ingredients) // disable highlighting items
.removeAttr('href');
$('.editme').editable("enable");
$('.editme').editable('http://localhost:8000/edit-ingredient/', {
indicator : 'Saving...',
tooltip : 'Click to edit...',
submit : 'OK',
cancel : 'Cancel'
});
}, function() {
$(this).attr('value', 'Edit item');
(shoppingList.$ingrLinks).attr('href', '#');
$('.editme').editable("disable");
(shoppingList.$ingrLinks).bind('click', shoppingList.ingredients) // re-enable highlighting items
});
}
};
$(document).ready(shoppingList.init);
Is there a way I could store the toggle event inside the editItems object literal and still have it working as expected?

editItems function looks really odd. I guess you just need to define 2 functions: startEdit and endEdit. And bind them on even and odd clicks using toggle.
var shoppingList = {
// Some code ...
init : function() {
// Bind on edit button click
this.$editButton.toggle(this.startEdit, this.endEdit);
},
startEdit : function() {
$(this).attr('value', 'Finish editing');
shoppingList.$ingrLinks.unbind('click', shoppingList.ingredients) // disable highlighting items
.removeAttr('href');
$('.editme').editable("enable");
$('.editme').editable('http://localhost:8000/edit-ingredient/', {
indicator : 'Saving...',
tooltip : 'Click to edit...',
submit : 'OK',
cancel : 'Cancel'
}),
endEdit: function() {
$(this).attr('value', 'Edit item');
(shoppingList.$ingrLinks).attr('href', '#');
$('.editme').editable("disable");
(shoppingList.$ingrLinks).bind('click', shoppingList.ingredients) // re-enable highlighting items
})
};
$($.proxy(shoppingList, 'init'));

Related

Remove and Restore datatables pagination click functionality

I have a datatables instance on a web page that has full numbers pagination. This includes First,Previous,Next and Last buttons plus the individual numbered buttons.
Each row in the table has an 'Edit' link. When I click it, I want to disable the pagination from working. When I click a 'Cancel' button, I want to restore the pagination functionality. I can do the first part easy enough, but I cannot restore the pagination click functionality. Here's my code:
function ghostPage(state)
{
// In this method, 'state' will be either true or false
// If it's true, remove the click handler
// If it's false, restore the click handler
if(state)
{
$('#displayTable_paginate').find('a').each(function(e){
$(this).off('click');
})
}
else
{
$('#displayTable_paginate').find('a').each(function(){
$(this).on('click');
})
}
}
Try this if you want to save the click handler and restore it later.
function saveClickHander(){
var $this;
$('#displayTable_paginate').find('a').each(function(e){
$this = $(this);
$this.data().originalClick = $this.data("events")['click'][0].handler;
})
}
function ghostPage(state)
{
// In this method, 'state' will be either true or false
// If it's true, remove the click handler
// If it's false, restore the click handler
if(state)
{
$('#displayTable_paginate').find('a').each(function(e){
$(this).off('click');
})
}
else
{
var $this;
$('#displayTable_paginate').find('a').each(function(){
$this = $(this);
$this.on('click', $this.data().originalClick);
})
}
}

How to make sure that click functions are only performed once

When the user clicks on either .class or #id, some changes are made to the css of both divs and the value of #id increases by 1. However, when the user clicks on either one of the divs, the changes should only be made once - if the user clicks again, nothing will happen unless the page is refreshed.
$('.class, #id').one('click', function(e) {
$('.class, #id').css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff',
});
$("#id").html(function(i, val) { return val*1+1 });
});
Above shows the code that I am using. As you can see, I have used .one to make sure that the code is only performed once. This works, but the problem is that the user can click on .class and then click on #div which means that the code can be performed twice.
How would I edit this so that the code can only be performed once - clicking on one div means the other div can not be clicked on.
You can set a data attribute on both objects and only increment the counter if that is not set:
$('.class, #id').one('click', function(e) {
if (!$(this).data("valueSet")) {
$('.class, #id').css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff'
}).data("valueSet", true);
$("#id").html(function(i, val) { return val*1+1 });
}
});
Or, if you know there are no other jQuery click handlers that you want to retain, you can unbind all jQuery click handlers from both objects:
$('.class, #id').one('click', function(e) {
$('.class, #id').off("click").css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff'
})
$("#id").html(function(i, val) { return val*1+1 });
});
Or, you can unbind just this specific event handler by putting the event handler in a named function:
function oneClick(e) {
$('.class, #id').off("click", oneClick).css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff'
})
$("#id").html(function(i, val) { return val*1+1 });
}
$('.class, #id').one('click', oneClick);
A little more generic scheme would create a custom function that will only ever perform its action once:
function oneAction(fn) {
var calledYet = false;
return function() {
if (!calledYet) {
calledYet = true;
return fn.apply(this, arguments);
}
}
}
Then, you can use this:
$('.class, #id').one('click', oneAction(function(e) {
// this will only ever be executed once
$('.class, #id').css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff'
})
$("#id").html(function(i, val) { return val*1+1 });
}));
I think you could use one with event delegation instead. That way you have a single handler for all targets and jQuery will automatically remove it once invoked.
$(document).one('click', '#first,#second', alert.bind(null, 'clicked'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="first">first</button>
<button id="second">second</button>
With your code it would be:
$(document).one('click', '.class, #id', function(e) {
//handle click
});
Here's another example showing how you could manually remove the handler after invocation in a safe way (without affecting other handlers) using a named function expression:
$('#first, #second').click(function someClickHandler(e) {
alert('clicked!');
$('#first, #second').off('click', someClickHandler);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="first">First</button>
<button id="second">Second</button>
You are setting two listeners, in fact. One on the .class and another on the #id.
This means you'll need to store a state variable and check it before performing any action.
var isClickable = true;
$('.class, #id').one('click', function(e) {
if(isClickable){
isClickable = false;
$('.class, #id').css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff',
});
$("#id").html(function(i, val) { return val*1+1 });
}
});
This is a better option than adding a state attribute to the actual DOM element.

Backbone: Toggle methods on some event

I want one button to toggle two methods in backbone but I'm having issues. I'm pretty much new to JS in general.
If you click on a button:
I want to show a hidden div
change the text of the button clicked
Then, if you click the button again (which has the new text and the hidden div is shown)
Change the text
Hide the shown div
The second method of .hide is not being fired? I'm wondering if this is because .hide is not in the DOM initially, because it's being added on the show method. Just a guess and maybe there's a better way to toggle methods on one class?
Here's my JS
'touchstart .share-btn' : 'show',
'touchstart .hide' : 'hide'
'show' : function (e) {
var view = this;
$(e.currentTarget).closest('.tile').find('.share-tools').fadeIn('fast');
$(e.currentTarget).addClass('hide');
if ($(e.currentTarget).hasClass('hide')){
$(e.currentTarget).find('.button-copy').closest('.button-copy').html('close');
}
},
'hide' : function (e) {
var view = this;
if($(e.currentTarget).hasClass('hide')) {
$('.share-tools').fadeOut('fast');
$(e.currentTarget).removeClass('hide');
$(e.currentTarget).find('.button-copy').closest('.button-copy').html('share');
}
},
Maybe reworking your code a bit will help. I've created a working jsfiddle based on what I think you're trying to accomplish.
Here is the relevant view code:
var View = Backbone.View.extend({
...
// Make it clear that these are the same element.
// Ensure they will not both fire by making them exclusive.
events: {
'mousedown .share-btn:not(.hide)' : 'show',
'mousedown .share-btn.hide' : 'hide'
},
'show' : function (e) {
console.log('show');
var $e = $(e.currentTarget);
$e.closest('.tile').find('.share-tools').fadeIn('fast', function () {
$e.addClass('hide');
});
$e.find('.button-copy').closest('.button-copy').html('close');
},
'hide' : function (e) {
console.log('hide');
var $e = $(e.currentTarget);
$e.closest('.tile').find('.share-tools').fadeOut('fast', function () {
$e.removeClass('hide');
});
$e.find('.button-copy').closest('.button-copy').html('share');
}
});
You can find the working jsfiddle here: http://jsfiddle.net/somethingkindawierd/7rfs9/
Try to return false in your event listener to prevent call both methods on first click.

Hide a text input on a dialog box of CKEditor

I'm working on a plugin in CKEditor which have as a goal to hide or show element depending on which of my check box is checked. I have those element defined :
contents :
[
{
id : 'tab1',
label : 'Configuration Basique',
elements :
[
{
type : 'checkbox',
id : 'check',
label : 'Vers une page web',
'default' : 'unchecked',
onClick : function(){
}
},
{
type : 'text',
id : 'title',
label : 'Explanation',
}
]
},
{
id : 'tab2',
label : 'Advanced Settings',
elements :
[
{
type : 'text',
id : 'id',
label : 'Id'
}
]
}
],
so now what i would like to do is to hide no disable the text input with the label and print it only when the box is checked. So i've seen that i should use something like that :
onLoad : function(){
this.getContentElement('tab1','title').disable();
},
but the thing is i don't want to disable it i want to hide and then print it if the user check the box (which is why i put a onClick function in my checkbox). i've tryed to use the hide() function but it doesn't work and also the setAttribute('style','display : none;')
Tia :)
If you actually want to hide (and not disable) the element you can do this using
this.getContentElement('tab1','title').getElement().hide();
The extra getElement() call returns the litteral DOM object for your contentElement object, so you can call hide()/show() at will on it.
The onClick properties is available and does work on uiElement although it is not documented. The biggest problem is the definition of "this" is not the same inside the event than other place in the config. You first have to get the dialog to get other fields:
{
type: 'checkbox',
id: 'check',
label: 'check',
onClick: function() {
var dialog = this.getDialog()
if(this.getValue()){
dialog.getContentElement('tab1','title' ).disable();
} else {
dialog.getContentElement('tab1','title' ).enable()
}
}
}
Your checkbox definition is correct but there's no such thing like onClick property in dialog uiElement definition. All you got to do is to attach some listeners and toggle your field. Here you go:
CKEDITOR.on( 'dialogDefinition', function( ev ) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if ( isThisYourDialog? ) {
...
// Toggle your field when checkbox is clicked or dialog loaded.
// You can also use getInputElement to retrieve element and hide(), show() etc.
function toggleField( field, check ) {
field[ check.getValue() ? 'enable' : 'disable' ]();
}
var clickListener;
dialogDefinition.onShow = function() {
var check = this.getContentElement( 'tab1', 'check' ),
// The element of your checkbox.
input = check.getInputElement(),
// Any field you want to toggle.
field = this.getContentElement( 'tab1', 'customField' );
clickListener = input.on( 'click', function() {
toggleField( field, check );
});
// Toggle field immediately on show.
toggleField( field, check );
}
dialogDefinition.onHide = function() {
// Remove click listener on hide to prevent multiple
// toggleField calls in the future.
clickListener.removeListener();
}
...
}
});
More docs: uiElement API, dialog definition API.

jQuery.off() is not removing binding

For some reason jQuery.off('click') doesn't seem to be working here. When the 'Yes' button is clicked in the model another model just pops up. What am I doing wrong?
code:
$(function(){
//If there are warnings on the page bind alert
if ($('.renewal-warning').length > 0){
(function (){
$('#signRentalContainer').on('click', '.renewal-warning', function(e){
var buttonHandle = this;
//Prevent submission
e.preventDefault();
//Show warning model
$.modal({
content: $('#renewalWarning').html(),
title: "Order Renewal Warning",
buttons: {
'Yes': function(win) { $(buttonHandle).off('click').click(); },
'No': function(win) { win.closeModal(); }
},
maxWidth: 250,
closeButton: false
});
});
})();
}
});
Pretty sure you're going to need to provide it the same element, as well as the same selector.
$('#signRentalContainer').off('click', '.renewal-warning');
In the .on() handler, this is the '.renewal-warning' element that was clicked, not the #signRentalContainer element.
If there are several of these '.renewal-warning' elements, and you only want to disable one at a time, the simplest way is to change its class so that it no longer matches the selector.
$(this).removeClass('renewal-warning')
.addClass('renewal-warning-disabled');
Because the this refer to the context of the handle function, not the function itself.
Try making it a named function, then refer to it when you call off:
$("body").off("click", '#signRentalContainer', buttonHandle);
BTW, any reason we can't use unbind directly here?
$("#signRentalContainer").unbind("click");

Categories

Resources