I've broken it again, and no idea how.
I have a CodePen of my recent activities.
What I've been trying to implement is a sortable function that checks first if there's only one #p_scents. If there is, it shouldn't be sortable (ie the .icon-sort shouldn't be activated). However if there is more than one, it should be sortable.
The problem I ran into however is after all but one has been deleted, the sortable functionality is still activated as it doesn't RE-check for how many #p_scents exist.
How can I fix this?
FYI somehow I broke the sortable functionality now o_O
$(function () {
var i = 1;
//ADD ROW
$('body').on('click', '.addPTbutton', function () {
var box = '<table class="manage-pt" id="' + i + '"><tr class="pt-entry"><td class="pt-toggle-group"><input class="pt-button togPTbutton" id="0" type="button" value="▾"><input class="pt-button addPTbutton" id="0" type="button" value="+"><input class="pt-button delPTbutton" id="' + i + '" type="button" value="-"></td><td class="pt-values"><div><input class="vendor" placeholder="*Vendor Name" type="text"><i class="icon-sort"></i><i class="icon-lock"></i></div><div><textarea class="ptCode" name="ptCode" placeholder="*Pixel Tag Code"></textarea></div><div class="page-select"><select><option value="AllPages">All Pages</option><option value="HomePage">HomePage</option><option value="VehicleDetailsPage">VehicleDetailsPage</option><option value="VehicleSearchResults">VehicleSearchResults</option><option value="ContactUsForm">ContactUsForm </option></select></div><div class="area-checkboxes"><p class="wheretosave">*Where?</p><input name="head" type="checkbox"><label for="head">Head</label><input name="body" type="checkbox"><label for="body">Body</label></div><hr/></td></tr></table>';
i++;
$("#p_scents").append(box);
return false;
});
//DELETE ROW
$('body').on('click', '.delPTbutton', function () {
var boxnum = $(".manage-pt").length;
if (boxnum <= '1') {
alert('Cannot Delete Last Remaining Row');
} else {
$(this).parents().eq(3).remove();
}
return false;
});
//TOGGLE BUTTON
$('body').on('click', '.togPTbutton', function () {
var hiddenarea = $(this).parent().next().children().next();
if ($(hiddenarea).is(':hidden')) {
//PT-VALUES OPENED
$(this).val('▾');
$(this).parent().next().children(0).children(0).attr('readonly', false);
} else {
//PT-VALUES HIDDEN
$(this).val('▸');
$(this).parent().next().children(0).children(0).attr('readonly', true);
}
//TOGGLE VISIBILITY OF HIDDEN AREA
hiddenarea.toggle();
});
//CHECKS FOR MORE THAN ONE 1 MANAGE-PT BEFORE ENABLES SORTABLE
$('body').on('click', '.icon-sort', function () {
if ($(".manage-pt").size() > 1) {
$('#p_scents').sortable({
disabled: false,
placeHolder: '.placeHolderHighlight',
handle: '.icon-sort',
});
} else $('#p_scents').sortable({
disabled: true,
});
});
//CHECK TO MAKE SURE ONLY ONE CHECKBOX IS SELECTED
var $onlyOne = $('.onlyOne');
$onlyOne.click(function () {
$onlyOne.filter(':checked').not(this).removeAttr('checked');
});
//LOCK BUTTON ON/OFF LOCKS FORM
$('body').on('click', '.icon-lock', function () {
$(this).toggleClass('locked');
var lockedarea = $(this).parents(0).eq(2);
$(lockedarea).find('input[type=text],input[type=checkbox],textarea,select').prop('disabled', function (_, val) {
return !val;
});
});
});
Your problem is here:
//CHECKS FOR MORE THAN ONE 1 MANAGE-PT BEFORE ENABLES SORTABLE
$('body').on('click', '.icon-sort', function () {...});
When make click on element ".icon-sort" is still sortable. You must use an action that makes the check before sort action begins: like mouseenter.
Here a jsfiddle
Related
I'm trying to active the seach per column on click of the related element.
I managed to get the search box on click but it doesn't perform the search
I'm not that expert with javascript and jQuery but this is my code:
// Setup - add a text input to each footer cell
$('#DataTable tfoot th').each(function () {
var title = $(this).text();
$(this).click(function (event) {
$(this).html('<input type="text" placeholder="Search ' + title + '" />');
$(this).unbind('click');
});
});
// DataTable
var table = $('#DataTable').DataTable({
initComplete: function () {
// Apply the search
this.api().columns().every(function () {
var that = this;
$('input', this.footer()).on('keyup change clear', function () {
if (that.search() !== this.value) {
that
.search(this.value)
.draw();
}
});
});
}
});
Is there also a way to make the code shorter?
Thank you
The input doesn't exist at the point where you attach your keyup change clear event handler to it. You'll need to use delegated events instead.
initComplete: function() {
this.api().columns().every(function() {
var that = this;
$(this.footer()).on('keyup change clear', 'input', function() {
if (that.search() !== this.value) {
that.search(this.value).draw();
}
});
});
}
You can use jQuery's one method to attach an event handler which will only be called once. You should also avoid creating multiple jQuery wrappers for the same input where you can.
$('#DataTable tfoot th').each(function () {
var $this = $(this);
$this.one("click", function (event) {
$this.empty().append($('<input/>').attr("type", "search").attr("placeholder", "Search " + $this.text()));
});
});
I am building a simple shopping list. Currently my code will delete an added list item when you click anywhere on the list item itself, I would like it to work where clicking on the UI button next to it will delete the entire item from the list, what I have tried will only delete the UI button itself. Thanks for the help, I am very much a novice
HTML
<div id="list">
<ul class="shopping"></ul>
</div>
jQuery
$(document).ready(function () {
function addItemToList(e) {
var addItem = $('#item').val();
$('.shopping').append('<li>' + '<button class="uibutton"></button>' + addItem + '</li>');
$('.uibutton').button({
icons: {
primary: "ui-icon-heart"
},
text: false
});
$('ul').on('click', 'li', function() {
$(this).remove();
});
$('#item').val('');
}
/*adds list item to list when cart icon is clicked, clears #item input field*/
$('#toadd').click(function (e) {
addItemToList(e);
});
/*adds list item to list when enter key is hit, clears #item input field*/
$('#item').keydown(function (e) {
if (e.which == 13) {
addItemToList(e);
}
});
});
You can make 2 changes like
$(document).ready(function () {
function addItemToList(e) {
var addItem = $('#item').val();
var $li = $('<li>' + '<button class="uibutton"></button>' + addItem + '</li>').appendTo('.shopping');
//target only newly added button
$li.find('.uibutton').button({
icons: {
primary: "ui-icon-heart"
},
text: false
});
$('#item').val('');
}
//use event delegation instead of adding the handler in another event handler...
$('ul.shopping').on('click', '.uibutton', function () {
$(this).closest('li').remove();
});
/*adds list item to list when cart icon is clicked, clears #item input field*/
$('#toadd').click(function (e) {
addItemToList(e);
});
/*adds list item to list when enter key is hit, clears #item input field*/
$('#item').keydown(function (e) {
if (e.which == 13) {
addItemToList(e);
}
});
});
Demo: Fiddle
I have to write code which finds all anchors and attaches a function that displays a popup of the elements text. My code is probably a mess, but I was able to get it working however the issue I have now is:
If I click link 1, then link 2, then click link 1 again, it displays link 2's text however if i click it again it displays the correct text.
I am not sure exactly how to rewrite or go about fixing this code to properly display the element which is clicked, text all the time.
here is a jsfiddle example: http://jsfiddle.net/2aLfL/1/
$(document).ready(function() {
function deselect(e) {
$('.pop').slideFadeToggle(function() {
e.removeClass('selected');
});
}
$(function() {
$('a').click(function(){
if($(this).hasClass('selected')){
deselect($(this));
} else {
$(this).addClass('selected');
$('.pop').slideFadeToggle();
var elText = $(this).text();
$('#elPop').html("<p>" + "<br><br>" + "You just clicked: <br><b>" + elText + "</b><br><br><br>" + "Click anywhere to Close" + "</p>");
console.log(this);
$("#closeWin").click(function () {
$('.anchorpop').hide();
});
}
return false;
});
});
$(function close(){
$(document).click(function(){
$('.anchorpop').hide();
});
});
$.fn.slideFadeToggle = function(easing, callback) {
return this.animate({ opacity: 'toggle', height: 'toggle' }, 'fast', easing, callback);
};
});
You're binding the following click handler
$("#closeWin").click(function () {
$('.anchorpop').hide();
});
inside <a> click handler so whenever a link is clicked, multiple handlers are being added.
You can avoid many unnecessary code using toggleClass() method.
You can also bind same event handlers to multiple elements by passing additional selectors.
after all your code boils down to
$(function () {
$('a').click(function () {
var htmlString = "<p>" + "<br><br>" + "You just clicked: <br><b>" + $(this).text() + "</b><br><br><br>" + "Click anywhere to Close" + "</p>"
$('.pop').html(htmlString).slideFadeToggle(function () {
$(this).toggleClass('selected');
});
return false;
});
$("#closeWin, .anchorpop").click(function () {
$('.anchorpop').hide();
});
});
and the custome slideFadeToggle function.
Updated Fiddle
Im using jQuery ui button to create divs that look like buttons dynamically. Clicking on these divs should open a dialog and clicking its icon should remove the div(button). Ive tried several different approaches but I cant seem to get the result I want.
Closest thing Ive achieved is by using onclick on both the icon & on the div itself, but the problem is that when clicking the icon I would first call the icon's onclick and then afterwards calling the div's onclick, which will cause the dialog to open after the div has been removed.
Ive also tried to add a disable property and set it to true on the div inside the icon's onclick and check for that inside the div's onclick but that dont work(I kinda get why.)
So my question is then: How can I create a button that will open a dialog when clicked on and with a icon that, when clicked on, removes the button?
Code:
function Add(value) {
var buttonid = "SearchResultBox" + ($("#SearchBoxAddedSearches .SearchResultBox").length + 1);
$("#SearchBoxAddedSearches").append("<div id='" + buttonid + "' class='SearchResultBox' onclick='ButtonClicked(this);'>" + value + "</div>");
$("#SearchBoxTextField").contents().filter(function () { return this.nodeType === 3; }).remove();
$('.SearchResultBox').button({
icons: {
primary: "ui-icon-circle-close"
}
}).delegate("span.ui-icon-circle-close", "click", function () {
var btnId = $(this).closest("div").remove().attr("aria-controls");
$("#" + btnId).remove();
});
$('.ui-icon-circle-close').attr('onclick', 'IconCloseClicked(this);');
}
function IconCloseClicked(value) {
$(value).parent().prop("disable", "true");
//alert($(value).parent().attr("id"));
alert("icon");
Remove($(value).parent());
}
function ButtonClicked(o) {
var test = $(o).prop("disable");
alert("div");
if ($(o).attr("disable") == undefined) {
Opendialog();
}
}
function Remove(value) {
$(value).remove();
}
function Opendialog() {
$("#dialog").dialog("open");
}
Ps. Reason why Ive used the button is because it is the widget that looks the most like what I want in jquery ui.
Updated(What I ended up with):
function Add(value) {
var buttonid = "SearchResultBox" + ($("#SearchBoxAddedSearches .SearchResultBox").length + 1);
$("#SearchBoxAddedSearches").append("<div id='" + buttonid + "' class='SearchResultBox'>" + value + "</div>");
$("#SearchBoxTextField").contents().filter(function () { return this.nodeType === 3; }).remove();
$('.SearchResultBox').button({
icons: {
primary: "ui-icon-circle-close"
}
}).click(function (e) {
Opendialog();
});
$('.ui-icon-circle-close').click(function (e) {
$(this).parent().remove();
e.stopPropagation();
});
}
function Opendialog() {
$("#dialog").dialog("open");
}
I'm assuming the icon is a child element of the button div. When the icon is clicked, you need to stop the click event bubbling to the parent div. You can do this with event.stopPropagation()
$('.icon').click(function(e){
e.stopPropagation();
});
I'm experiencing weird behavior with jquery ui autocomplete when using it to create a combobox. Whenever I click on the scrollbar to scroll through the list of results AND then click on my combobox button to close the results the results list closes and then opens again. I expect it to close the menu.
Steps to Repro
open jsfiddle demo
Type 'i' in the autocomplete OR hit the dropdown button.
Click on the vertical scroll to scroll the results
Click on the dropdown button
Script to Create Button
this.button = $("<button type='button'> </button>")
.attr({ "tabIndex": -1, "title": "Show all items" })
.insertAfter(input)
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass("ui-corner-all")
.addClass("ui-corner-right ui-button-icon")
.click(function () {
// when i put breakpoint here, and my focus is not on input,
// then this if steatment is false????
if (input.autocomplete("widget").is(":visible")) {
input.autocomplete("close");
return;
}
// work around a bug (likely same cause as #5265)
$(this).blur();
// pass empty string as value to search for, displaying all results
input.autocomplete("search", "");
input.focus();
});
CSS (force long results menu to scroll)
.ui-autocomplete {
max-height: 100px;
overflow-y: auto;
/* prevent horizontal scrollbar */
overflow-x: hidden;
/* add padding to account for vertical scrollbar */
padding-right: 20px;
}
/* IE 6 doesn't support max-height
* we use height instead, but this forces the menu to always be this tall
*/
* html .ui-autocomplete {
height: 100px;
}
My solution could be closing the widget even if focus is transferred to widget itself and not the input element?
Any ideas how to modify this code so it behaves this way?
Based on issues with the various click and mouse events for the automplete widget, I came up with this: jsFiddle example.
jQuery:
var input = $('#txtComplete');
var data = [];
var isOpen = false;
function _init() {
for (var idx = 0; idx <= 100; idx++) {
data.push('item: ' + idx);
};
input.autocomplete({
source: data,
minLength: 0,
open: function(event, ui) {
isOpen = true;
},
select: function(event, ui) {
isOpen = false;
}
});
}
function afterInit() {
var button = $("<button type='button'> </button>").attr("tabIndex", -1).attr("title", "Show all items").insertAfter(input).button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
}).removeClass("ui-corner-all").addClass("ui-corner-right ui-button-icon").click(function(event) {
input.focus();
if (isOpen) {
input.autocomplete("close");
isOpen = false;
} else {
input.autocomplete("search", "");
event.stopImmediatePropagation();
}
});
}
$(window).click(function() {
input.autocomplete("close");
isOpen = false;
});
$(function() {
_init();
afterInit();
});
The problem is because of a work around in jquery ui autocomplete. There is a mousedown event setup to close the menu under certain conditions. In one of the conditions it checks to see if the item that raised the mousedown is part of the autocomplete widget. If not, it closes the menu. Since you are tacking on combobox behaviour and your button is not part of the autocomplete widget, a click on the button is closing the menu because of this event.
You can see the offending condition with the reason why it is there starting at line 205 in the autocomplete source on github. It is probably worth raising the issue on the jquery ui forums since their combobox demo has this bug too.
UPDATE
This replacement event is based off of jquery-ui 1.8.18. This event has changed and will very likely change again. You might need to update this code manually with each release if you go this route.
You can patch the mousedown event to not close the menu if it was your combo button that was clicked by running the following after you create your autocomplete (jsfiddle demo).
var input = $('#combotextbox').autocomplete(/*options*/);
input.data('autocomplete').menu.element.unbind('mousedown').mousedown(function(event) {
var self = input.data('autocomplete');
event.preventDefault();
// clicking on the scrollbar causes focus to shift to the body
// but we can't detect a mouseup or a click immediately afterward
// so we have to track the next mousedown and close the menu if
// the user clicks somewhere outside of the autocomplete
var menuElement = self.menu.element[0];
if (!$(event.target).closest(".ui-menu-item").length) {
setTimeout(function() {
$(document).one('mousedown', function(event) {
var t = $(event.target);
if (event.target !== self.element[0] && event.target !== menuElement && !$.ui.contains(menuElement, event.target) && !t.hasClass('ui-combo-trigger') && !t.parent().hasClass('ui-combo-trigger')) {
self.close();
}
});
}, 1);
}
// use another timeout to make sure the blur-event-handler on the input was already triggered
setTimeout(function() {
clearTimeout(self.closing);
}, 13);
});
This removes the current mousedown event and then adds it back in with an added check to see if the element that triggered the event or its parent (button clicked or ui-icon inside the button is clicked) has a class ui-combo-trigger.
The code to create your button is relatively unchanged. We just need to add the new class ui-combo-trigger.
var button = $("<button type='button'> </button>").attr("tabIndex", -1).attr("title", "Show all items").insertAfter(input).button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
}).removeClass("ui-corner-all").addClass("ui-corner-right ui-button-icon ui-combo-trigger").click(function(event) {
// when i put breakpoint here, and my focus is not on input,
// then this if steatment is false????
if (input.autocomplete("widget").is(":visible")) {
input.autocomplete("close");
return;
}
// work around a bug (likely same cause as #5265)
$(this).blur();
// pass empty string as value to search for, displaying all results
input.autocomplete("search", "");
input.focus();
event.stopImmediatePropagation();
});
Try this jsfiddle. I think it ll help you.
var input = $('#txtComplete');
var data = [];
var openCheck = false;
function _init() {
for (var idx = 0; idx <= 100; idx++) {
data.push('item: ' + idx);
};
input.autocomplete({
source: data,
minLength: 0,
open: function(event, ui) {
openCheck = true;
},
select: function(event, ui) {
openCheck = false;
}
});
}
function afterInit() {
var button = $("<button type='button'> </button>").attr("tabIndex", -1).attr("title", "Show all items").insertAfter(input).button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
}).removeClass("ui-corner-all").addClass("ui-corner-right ui-button-icon").click(function(event) {
if (openCheck) {
input.autocomplete("close");
openCheck = false;
} else {
input.autocomplete("search", "");
}
});
}
$(function() {
_init();
afterInit();
});
Brian explained the problem very good. With jquery ui 11 you can do something like:
wasOpen = false;
$button
.mousedown(function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.click(function() {
input.focus();
// Close if already visible
if ( wasOpen ) {
return;
}
see example at http://jqueryui.com/autocomplete/#combobox