How to change the containment of an object on load in jQuery - javascript

I am currently trying to change the containment of jquery page items as a page loads. The current set up is that each of the items is associated with a class which then sets up the draggable properties of all the items.
Given particular actions, I need to be able to change the containment of particular bars to allow them to move inside different bounds than those initially set.
I've attached a jsFiddle (http://jsfiddle.net/cyVYq/28/) demonstrating what I am currently doing which for some reason will not break the original containment that has been set. Any help would be appreciated.
//find the elements that have changed on pback
var newlyConstrainedItems = $("[id*=container]");
$.each(newlyConstrainedItems, function (key, value) {
var barID = this.id.split("_");
$(barID[1]).draggable({
containment: $("#" + this.id)
});
});
Thanks

You forgot the hash symbol in your id selector:
var newlyConstrainedItems = $("[id*=container]");
$.each(newlyConstrainedItems, function (key, value) {
var barID = this.id.split("_");
$('#'+barID[1]).draggable({
containment: $("#" + this.id)
});
});

Related

Kendo ListBox: Return dropped items in order

I am using two listboxes, connected with each other, that allow drag and drop between the two. While using the reorder code found in another thread fixes the issue with reordering items within the same list, it doesn't address the issue when dragging and dropping an item from one listbox to the other. I understand that is because this isn't a "reorder" action, it is a "drop" action. I've tried many different angles, like using the "add" event, but there is no "offset" property in the (e) object.
How can I accomplish the same thing, that is, keep the dropped item in the order it is visually dropped?
Here is my widget function with the reorder event that properly orders the items as they are displayed in the listBox (why this doesn't happen automatically is beyond me!). Remember, the reorder event only occurs when moving items within the same listBox, not when dragging an item from one listBox to another.
$("#myMenus").kendoListBox({
draggable: true,
connectWith: "baseMenus",
dropSources: ["baseMenus"],
add: function(e) {
console.log('ADD');
console.log(e);
},
reorder: function(e) {
e.preventDefault();
var dataSource = e.sender.dataSource;
var dataItem = e.dataItems[0];
var index = dataSource.indexOf(dataItem) + e.offset;
dataSource.remove(dataItem);
dataSource.insert(index, dataItem);
},
});
I've managed to accomplish the same task, depending on the html hint that appears while dropping the item in the second listbox. I've modified your code with the solution.
$("#myMenus").kendoListBox({
draggable: true,
connectWith: "baseMenus",
dropSources: ["baseMenus"],
add: function(e) {
e.preventDefault();
var dataSource = e.sender.dataSource;
var dataItem = e.dataItems[0];
var index = $('li.k-drop-hint').index();
dataSource.insert(index, dataItem);
},
reorder: function(e) {
e.preventDefault();
var dataSource = e.sender.dataSource;
var dataItem = e.dataItems[0];
var index = dataSource.indexOf(dataItem) + e.offset;
dataSource.remove(dataItem);
dataSource.insert(index, dataItem);
},
});

Add class to link slug based off array of slugs

I am creating a recipe tool that takes a user's input via selected checkboxes. See here: zelda.wptoolkit.us
Part One:
I have a script that will create an array of slugs based off of the selected input values. When a user clicks a checkbox, the associated slug is added to an array called checkedAttr.
<script>
var checkedAttr = [];
$('#wp-advanced-search :checkbox').change(function()
{
checkedAttr = [];
$('#wp-advanced-search :checkbox').each(function(i, item){
if($(item).is(':checked'))
{
checkedAttr.push($(item).val());
}
});
console.log("checkedAttr:", checkedAttr);
});
</script>
Part Two:
I am trying to use the code below to .addClass to any links that contain a slug found in the array from part one.
The link structure: http://zelda.wptoolkit.us/tag/any-crab/
The code:
<script type="text/javascript">
jQuery(function() {
jQuery('#wpas-results-inner > div > div > p > a[href^="/tag/' +
location.pathname.split("/") this.checkedAttr[0] + '"]').addClass('active');
});
</script>
What I am aiming to do is target the links in each card, then add a class to the links whose slug is found in my array. The end goal is to highlight checked 'ingredients' and fade out ingredients that haven't been checked.
I am not exactly sure how to make this function check my array for each slug, I would love to learn what steps are needed to accomplish this!
I am also not certain if my jQuery CSS path is correctly targeting the links
Thanks for any insights!
If you are looking for something like when select particular checkbox, all the card related to that checkbox should be enabled(lets say apply any class active) and once you dis-select the checkbox, we need to remove that particular class from all related checkbox??
you can check the given fiddle.
https://jsfiddle.net/stdeepak22/x1L95dw3/1/
var checkedAttr = [];
$('#checkBoxForCategory :checkbox').change(function()
{
var cardCategory = $(this).val();
var allCards = $('.myCard[card-category=' + cardCategory + ']');
if($(this).is(':checked'))
{
//add the selected category to array
checkedAttr.push(cardCategory);
//add the `active` class for all the card belongs to selected category
$(allCards).each(function()
{
$(this).addClass('active');
});
}
else
{
//remove from array
var index = checkedAttr.indexOf(cardCategory);
checkedAttr.splice(index, 1);
//remove the class for all the card belongs to selected category
$(allCards).each(function()
{
$(this).removeClass('active');
});
}
console.log("checkedAttr:", checkedAttr);
});

jQuery UI Sortable containment unable to detect placeholder

So I was working on this application where I want people to be able to drag items from one table data to the other table data, which must be contained within the parent table row.
But whenever I drag it around it seems to stick to the containment excluding the height of any placeholders.
Try it yourself: http://jsfiddle.net/2wy8R/
Any idea of how I can make it select the parent of the parent? Of not, then, how can I make the placeholders count?
Greetings
.
Update: YouTube video of the problem http://youtu.be/PMXcQvJmRGw
OK, here you go. Overridden the default containment as it seems buggy with your scenario. Let me know if this is not a good idea but it seems to work:
http://jsfiddle.net/2wy8R/6/
$('#first, #second').sortable({
connectWith: '.sortable',
placeholder: 'placeholder',
start: function(event, ui) {
ui.placeholder.height(ui.item.height() - 4);
var p = $(ui.helper);
var tr = p.closest("tr");
$(document).mousemove(function(e) {
var pOffset = p.offset();
var trOffset = tr.offset();
if (pOffset.left < trOffset.left) {
p.css({left: trOffset.left});
}
if (pOffset.left + p.width() > trOffset.left + tr.width()) {
p.css({left: trOffset.left + tr.width() - p.width()});
}
if (pOffset.top < trOffset.top) {
p.css({top: trOffset.top});
}
if (pOffset.top + p.height() > trOffset.top + tr.height()) {
p.css({top: trOffset.top + tr.height() - p.height()});
}
});
}
}).disableSelection();
just be careful with it though, as this keeps adding mousemove events to the document. you may want to unbind mousemove before binding it...

Select2 Dynamic elements not reacting to event

I am using Select2 which works great. However I am using below code to create new dynamic select2 drop down but they do not react/open when clicking on them.
var relationshipcounter = 0;
$('#AddMoreRelationships').click(function () {
var $relationship = $('.relationship'); // div containing select2 dropdown
var $clone = $relationship.eq(0).clone();
$clone[0].id = 'id_' + ++relationshipcounter;
$relationship.eq(-1).after($clone);
$relationship.find('select').trigger('change'); // not working
});
Screenshot:
JSFIDDLE:
http://jsfiddle.net/pHSdP/133/
I had this exact problem and, of course, the first thing I tried was a deep copy with data:
el.clone(true,true);
Which did not work. Instead the best method I found was:
el=other_el.clone()_etc; // cloning the old row
el.find('.select2-container').remove();
el.find('select').select2({width: 268});
el in both of these snippets is the div row that contains the select and so the Select2 element.
Essentially what I do in the second snippet is remove the "old" select2 which will always have the class of .select2-container and then recreate it on all found select elements within my new row.
You need to call clone with the true argument to copy over events and data as well. Otherwise only the element gets cloned, not the events that are bound to it.
$relationship.eq(0).clone(true);
Docs:http://api.jquery.com/clone/
Ok so issue is resolved, fiddle:
http://jsfiddle.net/WrSxV/1/
// add another select2
var counter = 0;
$('#addmore').click(function(){
var $relationship = $('.relationship');
var $clone = $("#RelationshipType").clone();
$clone[0].id = 'id_' + ++counter;
$clone.show();
$relationship.eq(-1).after($clone);
$clone.select2({ "width" : "200px" });// convert normal select to select2
//$('body').select2().on('change', 'select', function(){
// alert(this.id);
//}).trigger('change');
return false;
});
After cloning your object you have to reassign event for em:
var $clone = $relationship.eq(0).clone();
$clone.on("click", function_name);
Use .on to bind dynamically inserted elements to events like
$('body').on('click','#AddMoreRelationships',function () {
});

Creating multiple droppable siblings that at positioned on top of eachother

I am trying to create multiple jquery droppables next to eachother where some parts might overlap, in these cases I want the one that is on top (z-index wise) to be greedy.
I have tried setting the greedy: true option in the droppable, but this does not seem to help. I have also tried to return false on the drop event and used event.stopPropagation();.
Here is a jsfiddle based on the demo page of jquery.
Is there any way to stop the drop event from propagating if there is another droppable triggering it, preferably the one that has the highest z-index?
Use document.elementFromPoint to check the element directly under the cursor. If it’s not your droppable, don’t do anything.
Add the following to the top of your drop: handler:
var droppable = $(this);
ui.helper.css({pointerEvents: 'none'});
var onto = document.elementFromPoint(event.clientX, event.clientY);
ui.helper.css({pointerEvents: ''});
if(!droppable.is(onto) && droppable.has(onto).length === 0) {
return;
}
Disabling pointer events on the helper is necessary for document.elementFromPoint to ignore the thing your dragging and only checking underneath. I’ve updated your jsFiddle for a quick demonstration. Note that the highlight still affects both elements. You should be able to change that by not letting jQuery UI do the highlighting but instead write it yourself on the draggables drag: event. I have, however, found this to be unusable in practice as this check (and disabling pointer events) is quite slow and may also cause flickering.
You need a function to check if the element is the highest visible element. Something is the highest visible when
The item is later in the dom list
It has a higher z-index set
The below function can be used to see if the current element (either in over method or drop method in the droppable setting) is in fact the highest visible element.
function isHighestVisible(cEl) {
cEl = $(this); //use this if you want to use it in the over method for draggable, else just pass it to the method
//get all active droppable elements, based on the classes you provided
var $list = $('.ui-widget-header.ui-state-active');
var listCount = $list.length;
var HighestEl = null;
var HighestZI = -1;
//one element is always highest.
if (listCount<=1) {
console.log(cEl.attr('id'));
return true;
}
//check each element
$list.each(function(i) {
var $el = $(this);
var id = $el.attr('id');
//try to parse the z-index. If its 'auto', return 0.
var zi = isNaN(parseInt($el.css('z-index'))) ? 0 : parseInt($el.css('z-index'));
if (zi>0) {
//z-index is set, use it.
//I add the listCount to prevent errors when a low z-index is used (eg z-index=1) and there are multiple elements.
//Adding the listCount assures that elements with a z-index are always later in the list then elements without it.
zi = zi + listCount;
} else {
//z-index is not set, check for z-index on parents
$el.parents().each(function() {
$par = $(this);
var ziParent = isNaN(parseInt($par.css('z-index'))) ? 0 : parseInt($par.css('z-index'));
if (ziParent>0) {
zi = ziParent;
return false;
}
});
}
//add the current index of the element to the zi
zi += i;
//if the calculated z-index is highest, change the highest element.
if (HighestEl==null || HighestZI<zi) {
HighestEl=$el;
HighestZI = zi;
}
});
//if the highest found active element, return true;
if (HighestEl.attr('id')==cEl.attr('id')) {
console.log(cEl.attr('id'));
return true;
}
//if all else fails, return false
return false;
}
If i had this issue i would use jQuery's .addclass
.droppablewidgetforce {
z-index: 1000 !important;
}
make a class as such so the layer stays on top no matter what.. this should fix the issue.
The greedy options is just for nested elements that have a droppable parent.
In your code the 2 droppable elements are siblings so the greedy option will not work:
<div id="droppable3" class="ui-widget-header">
<p>Outer droppable</p>
</div>
<div id="droppable3-inner" class="ui-widget-header">
<p>Inner droppable (greedy)</p>
</div>
Here is a messy workaround if you still want to use siblings instead of parents and children.
Live code example.
function normalDraggedOver() {
$( this ).addClass( "ui-state-highlight" )
.find( "> p" )
.html( "Droppeeeed!" );
}
var options = {
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
greedy: true,
drop: normalDraggedOver
};
var options2 = {
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
disabledClass: "ui-state-disabled",
hoverStateClass: "ui-state-hover",
greedy: true,
greedyWithSibligs: true,
drop: normalDraggedOver,
over: function () {
/* if we have previous siblings of the inner element we handle them as parents */
if(options2.greedyWithSibligs && $(this).prev().length > 0) {
$(this).siblings().slice(0, $(this).index())
.removeClass(options2.hoverClass)
.droppable('disable')
.removeClass(options2.disabledClass)
.removeClass(options2.hoverStateClass);
}
},
out: function () {
/* all the siblings of the inner element that were handled as parents act as one*/
if(options2.greedyWithSibligs && $(this).prev().length > 0) {
$(this).siblings().slice(0, $(this).index())
.droppable('enable')
.addClass(options2.hoverClass);
console.log($(this).attr('id'));
}
}
};
If just want it to look the same you can set the #droppable3 to position: relative and set the child #droppable3-inner to position: absolute.
HTML:
<div id="droppable3" class="ui-widget-header">
<p>Outer droppable</p>
</div>
<div id="droppable3-inner" class="ui-widget-header">
<p>Inner droppable (greedy)</p>
</div>
Here is the live example

Categories