I am trying to remove elements of an array which contains either Groups(containing shapes) or simply Shapes(line, Rect, Circle etc) as its elements. My function is something like below:
deleteSelectedShape = function () {
var i,
shapeObj,
selectedObjects = currentContext.getSelectedObjects(),
shapeLayer = currentContext.getShapeLayer();
if (selectedObjects && selectedObjects.length > 0) {
for (i = 0; i < selectedObjects.length; i += 1) {
shapeObj = selectedObjects[i];
// shapeObj.remove(); results same error as mentioned at last
if (shapeObj.nodeType === "Group") {
shapeObj.destroyChildren();
}
else{
shapeObj.destroy();
}
}
}
selectedObjects = [];
shapeLayer.draw();
};
I tried this also
if (shapeObj.nodeType === "Group") {
var childs = [];
childs = shapeObj.getChildren();
for (var j = 0; j < childs.length; j++) {
childs[j].remove();
}
}
else{
shapeObj.remove();
}
}
}
Here Individual shapes are getting deleted but if there is group in array, it is giving error :
TypeError: this.getParent(...) is undefined in Kineticjs file
Please suggest me proper idea. Thank you !!!
One problem: When removing items from an array, you have to iterate through that array in reverse.
var i=selectedObjects.length-1;
while( i-- >=0 ){
var shapeObj = selectedObjects[i];
if (shapeObj.nodeType === "Group") {
shapeObj.destroyChildren();
}else{
shapeObj.destroy();
}
}
Related
Very new to javascript and can't figure out what I'm doing wrong. Trying to assign the className of a <div> element to a var, and I get this error.
scripts.js:30 Uncaught TypeError: Cannot read property '0' of undefined
at checkWinner (scripts.js:30)
at HTMLDivElement.buttonClick (scripts.js:25)
When I try to figure out if the property even exists, the console is leading me to believe it does. This seems like conflicting info to me.
winLines[0][0].className
"xButt"
Any help is appreciated. I'm sure it's something basic. Here's the code just in case.
var turns = 0;
var gameButtons = Object.values(document.querySelectorAll('.gameButton'));
var winLines= [
[gameButtons[0], gameButtons[1], gameButtons[2]]
/* other arrays go hear */
];
for (let i = 0; i < gameButtons.length; i++) {
gameButtons[i].textContent = null;
gameButtons[i].addEventListener('click', buttonClick);
}
function buttonClick(e) {
console.log(e.target.id + ": You clicked me!");
if (turns % 2 == 0) {
e.target.className = 'xButt';
e.target.textContent = 'X';
e.target.style.backgroundColor = 'green';
} else {
e.target.className = 'oButt';
e.target.textContent = 'O';
e.target.style.backgroundColor = 'blue';
}
turns++;
checkWinner();
}
function checkWinner() {
for (let i = 0; i <= winLines.length; i++) {
let markOne = winLines[i][0].className;
let markTwo = winLines[i][1].className;
let markThree = winLines[i][2].className;
if (markOne === markTwo && markOne === markThree) {
alert("Awww sh********t!");
}
}
}
Your loop has more iterations than your array has elements.
Change the loop like so:
for (let i = 0; i < winLines.length; i++)
The undefined error comes because you're trying winLines[1][0] which doesn't exist because winLines only has one element (at index 0)
I am trying to update a text on a click event, but somehow the index of the foreach always give me the first iteration 0, what am I missing:
var sliderTitles = document.getElementsByClassName('avia-caption-title');
var nextSlideBtns = document.getElementsByClassName('next-slide');
var prevSlideBtns = document.getElementsByClassName('prev-slide');
for (var i=0; i < nextSlideBtns.length; i++) {
nextSlideBtns.item(i).onclick = setBtnNames();
}
setBtnNames();
function setBtnNames() {
console.log("clickedd");
Array.from(nextSlideBtns).forEach(
function(element, index, array) {
console.log(index); // always returns 0
if(index == 5) {
element.innerHTML = sliderTitles[0].innerHTML;
} else {
element.innerHTML = sliderTitles[index+1].innerHTML;
}
}
);
}
I'm basically trying to loop through an array to check if an item already exists:
If the the item exists, remove it
If the item does not exist, push it to the array
However my code only allows me to add one item only. It ignores every other value I'm trying to add.
var inclfls = []; //new empty array
function addfile(val) {
if (inclfls.length != 0) {
for (var i = 0; i < inclfls.length; i++) {
if (inclfls[i] == val) {
a.style.background = "#999";
inclfls.splice(i, 1); //remove it
}
else {
a.style.background = "#2ECC71";
inclfls.push(val); //push it
}
}
}
else {
a.style.background = "#2ECC71";
inclfls.push(val);
}
alert(inclfls.length);
}
What am I doing wrong?
with array methods, its much simpler:
function addfile(val) {
var index=inclfls.indexOf(val);
if(index===-1){
inclfls.push(val);
a.style.background = "#999";
}else{
inclfls.splice(index,1);
a.style.background = "#2ECC71";
}
}
This function match sets an attribute (collapsed) to true or false depending on
the value of a string :
function match(children) {
var data = $scope.treeData
for (var i = 0; i < data.length; i++) {
var s = data[i]
for (var i2 = 0; i2 < s.children.length; i2++) {
var s2 = s.children[i2]
for (var i3 = 0; i3 < s2.children.length; i3++) {
for (var i4 = 0; i4 < s2.children[i3].children.length; i4++) {
var text = "";
if ($scope.searchText == undefined) {
text = ""
} else {
text = $scope.searchText
}
if (s2.children[i3].children[i4].label
.toLowerCase() === text.toLowerCase()) {
s2.children[i3].collapsed = false
}
}
}
}
}
}
Excluding the bad use of variable names i3,i2 etc is there a cleaner method ?
As the inner most loop requires access to the outer loop can recursion still be used ?
Update :
Data structure :
[{"label":"test","collapsed":false,"children":[{"label":"test","collapsed":false,"children":[],"$$hashKey":"002"}],"$$hashKey":"001"}]
Update 2 :
Using a recursive function but the string 'test' is not being matched :
http://jsfiddle.net/U3pVM/19196/
fiddle src :
<div ng-app>
<h2>Todo</h2>
<div ng-controller="TodoCtrl">
</div>
</div>
function TodoCtrl($scope) {
var json = [{"label":"test","collapsed":false,"children":[{"label":"test","collapsed":false,"children":[],"$$hashKey":"002"}],"$$hashKey":"001"}]
var searchText = 'test'
function match(node, searchText){
angular.forEach(node.children, function(idx, child){
node.collapsed = child.label.toLowerCase === searchText.toLowerCase
console.log(node.collapsed)
if(child.children.length > 0){
match(child, searchText);
}
});
}
match(json, searchText);
}
Please try this :
function match2(obj) {
if (obj.children) {
for (var i = 0; i < obj.children.length; i++) {
match2(obj.children[i]);
}
}
else {
var text = $scope.searchText ? $scope.searchText : "";
if (obj.label
.toLowerCase() === text.toLowerCase()) {
obj.collapsed = false
}
}
Your JSFiddle is very nearly there. I made a couple of changes for this working JSFiddle.
First, you were passing an array into match and not an object. I changed your json variable to be json instead by removing the outer [], but you could also have fixed this by passing in json[0].
The other change was that you had the two parameters, child and idx, were the wrong way round.
function match(node, searchText){
angular.forEach(node.children, function(child, idx){
node.collapsed = child.label.toLowerCase === searchText.toLowerCase
console.log(node.collapsed)
if(child.children.length > 0){
match(child, searchText);
}
});
}
Here's another way of doing it, using some:
function match (node, searchText) {
node.collapsed = node.children.some(function(child) {
return child.label.toLowerCase === searchText.toLowerCase;
});
angular.forEach(node.children, function(child, idx){
match(child, searchText);
})
}
I think something like this may work for you. I don't know anything about angular there might be something there that would make it easier.
var searchText = ($scope.searchText == undefined) ? "": $scope.searchText;
match($scope.treeData, searchText);
function match(node, searchText){
$.each(node.children, function(idx, child){
node.collapsed = child.label.toLowerCase === searchText.toLowerCase
if(child.children.length > 0){
match(child, searchText);
}
});
}
Im not sure why this isnt working and would love some help with it! And yes i have looked at this
Im trying to set multiple options in a select element as selected using an array holding the values i want selected and interating through both the array and the options in the select element. Please find code below:
// value is the array.
for (var j = 0; j < value.length; j++) {
for (var i = 0; i < el.length; i++) {
if (el[i].text == value[j]) {
el[i].selected = true;
alert("option should be selected");
}
}
}
After completing these loops nothing is selected, even though the alert() fires.
Any ideas are welcome!
Thanks
CM
PS (not sure whats happened to the code formatting).
EDIT: Full function
if (CheckVariableIsArray(value) == true) {
if (value.length > 1) { // Multiple selections are made, not just a sinle one.
var checkBoxEl = document.getElementById(cbxElement);
checkBoxEl.checked = "checked";
checkBoxEl.onchange(); // Call function to change element to a multi select
document.getElementById(element).onchange(); // Repopulates elements with a new option list.
for (var j = 0; j < value.length; j++) {
for (var i = 0; i < el.length; i++) {
if (el[i].text === value[j]) {
el[i].selected = true;
i = el.length + 1;
}
}
}
//document.getElementById(element).onchange();
}
}
else {
for (var i = 0; i < el.length; i++) {
if (el[i].innerHTML == value) {
el.selectedIndex = i;
document.getElementById(element).onchange();
}
}
}
Works for me. Are you setting el and value correctly? And are you sure you want to look at each option's innerHTML instead of it's value attribute?
See the jsFiddle.
HTML:
<select id="pick_me" multiple="multiple">
<option>Hello</option>
<option>Hello</option>
<option>Foo</option>
<option>Bar</option>
</select>
JS:
var value = ['Foo', 'Bar'],
el = document.getElementById("pick_me");
// value is the array.
for (var j = 0; j < value.length; j++) {
for (var i = 0; i < el.length; i++) {
if (el[i].innerHTML == value[j]) {
el[i].selected = true;
//alert("option should be selected");
}
}
}
Well, first of all, you must set the html select control multiple property, something like this "<select multiple="multiple">...</select>", and then you can use the javascript function SetMultiSelect (defined as below) to set the select html control:
function SetMultiSelect(multiSltCtrl, values)
{
//here, the 1th param multiSltCtrl is a html select control or its jquery object, and the 2th param values is an array
var $sltObj = $(multiSltCtrl) || multiSltCtrl;
var opts = $sltObj[0].options; //
for (var i = 0; i < opts.length; i++)
{
opts[i].selected = false;//don't miss this sentence
for (var j = 0; j < values.length; j++)
{
if (opts[i].value == values[j])
{
opts[i].selected = true;
break;
}
}
}
$sltObj.multiselect("refresh");//don't forget to refresh!
}
$(document).ready(function(){
SetMultiSelect($sltCourse,[0,1,2,3]);
});
Ran into this question and wasn't satisfied with the answers.
Here's a generic, non-jQuery version. It utilises Array.indexOf where possible, but falls back to a foreach loop if it isn't available.
Pass a node into the function, alongside an array of values. Will throw an exception if an invalid element is passed into it. This uses === to check against the value. For the most part, make sure you're comparing the option's value to an array of strings.
E.g. selectValues( document.getElementById( 'my_select_field' ), [ '1', '2', '3'] );
var selectValues = (function() {
var inArray = ( function() {
var returnFn;
if( typeof Array.prototype.indexOf === "function" ) {
returnFn = function(option, values) {
return values.indexOf( option.value ) !== -1;
};
} else {
returnFn = function(option, values) {
var i;
for( i = 0; i < values.length; i += 1 ) {
if( values[ i ] === option.value ) {
return true;
}
}
return false;
}
}
return returnFn;
}() );
return function selectValues(elem, values) {
var
i,
option;
if( typeof elem !== "object" || typeof elem.nodeType === "undefined" )
throw 'selectValues() expects a DOM Node as it\'s first parameter, ' + ( typeof elem ) + ' given.';
if( typeof elem.options === "undefined" )
throw 'selectValues() expects a <select> node with options as it\'s first parameter.';
for( i = 0; i < elem.options.length; i += 1 ) {
option = elem.options[ i ];
option.selected = inArray( option, values );
}
}
}());