javascript remove multiple objects from canvas with unique attribute - javascript

i'm using fabric js and trying to remove group of items when try to remove the parent item of group. following is my code.
jQuery(document).on('click', ".deleteBtn", function () {
if (canvas.getActiveObject()) {
var product_id = canvas.getActiveObject().get('product_id');
}
var canvasObj = canvas.getObjects();
for(var i = 0; i < canvasObj.length; i++){
var objRef = canvasObj[i];
var accessoryId = objRef.get('accessory_product_id');
var product_type = objRef.get('product_type');
if(accessoryId == product_id && product_type == "accessory"){
canvas.remove(objRef);
}
}
});
code is actually working, but not removing all items with same accessoryId and product_type parent item which is the active object trying to remove and two other items are removing properly. only two items left on canvas. there are all 5 items in group. those are images. i'm unable to find the issue please help. thanks!
HTML code
<div id="content-tab-3" class="visualiser-product-category content-tab active">
<ul>
<li>
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter_Spice.png" class="visualizer-product-img" alt="Placeholder" data-quantity="1" data-product_type="parent" data-product_id="343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Desk-Floral.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Garland.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Tabletop.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Wreath.jpg" class="hide accessory-343">
</li>
</ul>
</div>

Hello i noticed on your code that you try to get the active's object id, but no matter if there is active object or not you proceed to the loop, to delete the objects!!
Maybe, that causes the problem.
I'm going to show an example with forEach() function, but proceed to delete objects ONLY if there is active object:
jQuery(document).on('click', ".deleteBtn", function () {
//only if there is active object, do i delete objects
if (canvas.getActiveObject()) {
//get productId of active object
var product_id = canvas.getActiveObject().product_id;
//loop on the canvas objects
canvas.getObjects().forEach(function (object) {
if(object.accessoryId == product_id && object.product_type == "accessory"){
canvas.remove(object);
}
});//end forEach
}//end if
});//end 'click'
Hope helps, good luck.

Related

Add class to divs after reload by targeting the "data" attribute

I have four cards with the class of "card", but each one has a different data attribute: eyes, torso, arms and legs.
<div class="card" data-lesson="eyes">eyes</div>
<div class="card" data-lesson="torso">torso</div>
<div class="card" data-lesson="arms">arms</div>
<div class="card" data-lesson="legs">legs</div>
Everytime the user clicks on a card, that card is given the class of "reading". Also, the browser looks at the data attribute of that card and stores it in an array, locally.
$(".card").click(function(){
$(this).addClass("reading")
localStorage.setItem("readingCards" , readingCards)
});
What I'm trying to do is: after the page reloads, give every card that matches the data attribute stored in the array the class of "reading" so that when the page refreshes the same cards will have this class.
You can just iterate through all elements having the card class with each() and check if the corresponding data attribute is included in the comma separated local storage string.
You can try this
https://jsfiddle.net/jL6o7dc4/1/
$(document).ready(function(){
var readingCards = localStorage.getItem("readingCards")!==null?localStorage.getItem("readingCards"):'';
$(".card").each(function(){
if(readingCards.includes($(this).data("lesson"))){
$(this).addClass("reading");
}
});
$(".card").click(function(){
$(this).addClass("reading");
if(!readingCards.includes($(this).data("lesson"))){
readingCards+=(readingCards.length>0?',':'')+$(this).data("lesson");
localStorage.setItem("readingCards",readingCards);
}
});
You can try this-
The HTML is
<div class="card" data-lesson="eyes">Card 1</div>
<div class="card" data-lesson="torso">Card 2</div>
<div class="card" data-lesson="arms">Card 3</div>
<div class="card" data-lesson="legs">Card 4</div>
The Javascript is-
// On ready get the localStorage item and set the readings
var readingCards = localStorage.getItem('readingCards');
readingCards = typeof readingCards === 'string' && readingCards.length > 0 ? JSON.parse(readingCards) : [];
if (readingCards.length > 0) {
$('.card').each(function(index) {
let lesson = $(this).data('lesson');
if (readingCards.indexOf(lesson) > -1) {
$(this).addClass('reading');
}
});
}
$('.card').on('click', function() {
if (!$(this).hasClass('reading')) {
$(this).addClass('reading');
}
let lesson = $(this).data('lesson');
if (readingCards.indexOf(lesson) === -1) {
readingCards.push(lesson);
}
localStorage.setItem('readingCards', JSON.stringify(readingCards));
});
Use the css selector ".card[data-lesson='AAA']" to uniquely identify the cards while iterating over the stored values.
var storedCards = localStorage.getItem("readingCards") || "";
storedCards = storedCards.split(',');
$.each(storedCards, function( index, value ) {
$(".card[data-lesson='" + value + "']").addClass("reading");
});
Store it as an array in localstorage and then it is a simple loop to set the class by selecting items by the attribute.
$(document).ready(function() {
// read the localstorage and obtain the stored cards
// if no value, just use an empty array
var readingCards = JSON.parse(localStorage.getItem('readingCards') || '[]')
// loop over the array and add the classes to our elements
readingCards.forEach(function(value) {
$('[data-lesson="' + value + '"]').addClass('reading')
})
// add the click event to the cards
$(".card").on('click', function() {
// get the card and toggle the class
var card = $(this)
card.toggleClass('reading')
// select all the cards that are active and turn them into an array
readingCards = $(".card.reading").map(function() {
return this.dataset.lesson
}).get()
// set the array to localstorage
localStorage.setItem('readingCards', JSON.stringify(readingCards))
})
})

Remove item from array by pressing button

I'm using angularJS to build a SPA. I am trying to delete an object from an array in my controller. I am using ng-repeat and can't seem to get my head around this. Here is the related html:
<div class="cat-button" ng-repeat="category in cats" category="category">
<button class=" close-button" ng-click="removeCat()">
<span class="glyphicon glyphicon-remove-sign" aria-hidden=true> </span> </button>{{category.name}}
</div>
This created a div with a button for every object that gets saved to my $scope.cats array. It works fine but I cant figure out how do I use the button in each div to delete that specific object.
When I click on the button , the function on my controller gets called, but this is where I get lost, how do I delete the specific object created dynamically by the user.
This is the related code on my controller:
//Function to delete category
$scope.removeCat = function () {
//I know I have to use splice on my array but how do I Identify the object that needs to be deleted from my array?
};
You can either pass on $index like so:
<button class=" close-button" ng-click="removeCat($index)">
and in your function:
$scope.removeCat = function (index) {
$scope.cats.splice(index,1);
}
or pass the whole item and use indexOf (the saver way)
<button class=" close-button" ng-click="removeCat(category)">
$scope.removeCat = function (item) {
$scope.cats.splice(myArray.indexOf(item), 1);
}
You can pass the index of the item you want to delete in the ng-click function:
<div class="cat-button" ng-repeat="category in cats" category="category">
<button class=" close-button" ng-click="removeCat($index)">
<span class="glyphicon glyphicon-remove-sign" aria-hidden=true> </span> </button>{{category.name}}
</div>
Then you can use this in your Angular controller like this:
$scope.removeCat = function (index) {
$scope.cats.splice(index, 1);
};
Update
Incase you don't want to pass in the index, instead you can also pass in the entire object and locate the index in your controller. The code below is setup to work on all browsers. (Just haven't tested it ;) )
$scope.removeCat = function (cat) {
// Using underscore
var index = _.indexOf($scope.cats, cat);
// Or using a for loop
for(var i = 0; i < $scope.cats.length; i++) {
//Assuming your cat object has an id property
if($scope.cats.id === cat.id) {
index = i;
break;
}
}
};
Or any other way to locate the index of an object in an array.
ng-click="removeCat(category)"
$scope.removeCat = function (categoryToDelete) {
var index = $scope.cats.indexOf(categoryToDelete);
$scope.cats.splice(index, 1);
};

how to create dynamic submenu using javascript

I create a menu. Now i want to create a dynamic submenu. I call an array from database using javascript. Now How to connect array element with the list of submenu using the javascript.
enter code here
// Request For array from database using function gameNames()
// I define array
var gameName = new Array();
// database responses and get array list in this array.
// I dont know how to code for create a array list as a submenu
div id = "bar">
<ul id = "ul1">
<li class = "li1">Games
<ul id = "submenu"><li></li></ul>
</li>
<li class = "li1">Stake</li>
<li class = "li1">Max Players</li>
</ul>
<img src = "css/images/table_menu.png" id = "tm"/>
<div id = "rmg">Real Money Game</div>
</div>
Here is a demo. The source code in the SubMenu() function is what you will want to use to create the list items from your array.
var gameName=['Game one','Game Two','Game three']
function SubMenu(){
//Set variable for the submenu ul element
var Submenu = document.getElementById('submenu');
//For loop - for each value in the array
for(var i=0; i<gameName.length; i++){
//Create new li/List Item
var Item = document.createElement('li');
//Set innerHTML for this element
Item.innerHTML=''+gameName[i]+'';
//Append new element to the submenu.
Submenu.appendChild(Item);
}
//---Demo use Only
document.getElementsByTagName("button")[0].remove();
//---
}
<button onclick="SubMenu();">Create</button>
<ul>
<li>Games
<ul id="submenu"></ul>
</li>
<li>Stake</li>
<li>Max PLayers</li>
<ul>
If you have any questions about the source code above, leave a comment below and I will get back to you as soon as possible. If this answers your question appreciation is shown by marking it.
I hope this helps. Happy coding!

jQuery find not working with object array

This code doesn't work
var next = $("#orders").find(".next");
if (next.length == 1) {
var address = $(next[0]).find(".directionsAddress");
var destination = $(address[0]).text();
}
<div id="orders" class="ui-sortable">
<div id="companyAddress" class="noDisplay">101 Billerica Avenue, North Billerica, MA</div>
<div id="companyPhone" class="noDisplay">9788353181</div><div class="next"></div>
<div class="lat">42.616007</div>
<div class="lng">-71.31187</div>
<div id="section1611" class="sectionMargin borderRad">
<div class="directionsAddress noDisplay">92+Swan+Street+Lowell+MA</div>
It is suppose to find one div with a class of "next" that I know exists on the page, then within that one item of the result set array, there will be one div with a class name of directionsAddress.
The "next" array is coming back with a length of 1, so it looks like the problem is with my $(next[0]).find because the address array is coming back as 0 length and I am making a syntax error of some sort that I don't understand.
This should do what you want. You need to find the parent (or alternatively, the sibling of .next) then try to find the applicable .directionsAddress.
var next = $("#orders").find(".next");
if (next.length == 1) {
var destination = $(next).parent().find(".directionsAddress");
alert($(destination).text());
}
Working fiddle: https://jsfiddle.net/00fgpv6L/

multidimensional object building in javascript using loops

So i have a html layout in which there are blocks (there are no fix number of them, because they can be created dynamically).
In these blocks there are boxes (again, they can be created dynamically)
The boxes contain *html element*s and also have different data attributes
So i need to create an object which looks like this
block1 = {
box1 : {
id : box1.data('id'),
content : box1.html()
},
box2 : {
id : box2.data('id'),
content : box2.html()
}
},
block2 = {
box3 : {
id : box3.data('id'),
content : box3.html()
}
}
Please don't write that the syntax is not correct, i know. I just tried to somehow illustrate what i want.
So my question is how do i do this with the help of jQuery?
Thank you in advanced
You can select all blocks and boxes and iterate over each of them using .each [docs]:
var blocks = {};
$('.block').each(function(index) {
var boxes = {};
$(this).find('.box').each(function(index) {
boxes['box' + index] = {
id: $(this).data('id');
content: $(this).html();
};
});
blocks['block' + index] = boxes;
});
You might not need an object of objects though, maybe an array of array suffices or would be even better, depending on what you intend to do with the data.
To learn more about how objects work, have a look at MDN - Working with Object.
Here is an idea:
1- Iterate over all of the blocks using some CSS selector.
2- Create a generic JS object and set a collection attribute called "boxes" to be an array
3- For each one, iterate over all the boxes inside it, again, using some CSS selector.
4- Create a generic JS object for each box and set the attributes as needed.
Code version
I think something like this would work (not tested):
var blocks = new Array();
$(".blocks").each(function(b) {
var my_block = {boxes: new Array()};
var $block = $(b);
$(".box", $block).each(function(box) {
var $box = $(box);
my_block.boxes.push({id: $box.attr("id"), content: $box.html()});
});
blocks.push(my_block);
});
You should take a look at Knockout.js, it's very comfortable to build an application like yours.
In detail: use Objects. Build an array for yourself, containing Objects with e.g. Block Name and all Child nodes.
<div id="lanesContainer" data-bind="foreach: blocks">
<div id="" class="dropLane laneDefault ui-widget-header ui-dialog ui-widget ui-corner-all ui-front ui-resizable">
<div class="ui-dialog-titlebar ui-helper-clearfix" data-bind="drop: {value: $data.dropTask}">
<p class="laneheader" data-bind="text: $data.title">Lane</p>
</div>
<ul data-bind="foreach: box">
<li class="ui-dialog-content laneItem" data-bind="drag: {value: $data}">
<div class="ui-widget-header laneItemHeader" data-bind="text: $data.Title"></div>
<div class="ui-widget-content laneItemBody" data-bind="text: $data.Description"></div>
<div class="ui-widget-content laneItemFooter">
<div class="ui-corner-all ui-state-default notification-important">
<span class="ui-icon ui-icon-notice" title="sometitle" data-bind="css: {'notification-important-hide': !$root.isElementImportant($data) }"></span>
</div>
</div>
</li>
</ul>
</div>
</div>
Is this useful?
Here is how to get an Object with nested Array of Childs:
function laneObject(title) {
var obj = new Object();
obj.title = title; //Identifier for Lane
obj.childs = []; //Elements of Lane to display
return obj;
}
I am not entirely sure of what your question is, but if you want to create blocks and boxes dynamically, I suggest you first of all use Arrays.
//All dynamically created blocks
blocks = [];
//Create blocks
for(var i = 1; i < 3; i++) {
var block = {
//All dynamically generated bloxes
boxes = [];
};
//Create boxes
for(var j = 1; j < 4; j++) {
block.box[j] = {
id : j,
content : '<span>html for box' + j + '</span>'
}
}
blocks[i] = block;
}

Categories

Resources