How to deactivate DragControls in Three.js? - three.js

I would like to stop DragControls functionality after checkbox deselection. I try to use removeEventListener, but it seems not to be working. Do you have any idea how to deactivate DragControls?
let dragControls;
function dragControlsStart() {
dragControls.addEventListener('dragstart', function (event) {
controls.enabled = false;
});
dragControls.addEventListener('dragend', function (event) {
controls.enabled = true;
});
}
function dragControlsStop() {
dragControls.removeEventListener('dragstart', function (event) {
controls.enabled = false;
});
dragControls.removeEventListener('dragend', function (event) {
controls.enabled = true;
});
}
function dragAndDropActivate() {
let checkBox = document.getElementById("dragAndDropCheckbox");
dragControls = new THREE.DragControls(meshes, camera, renderer.domElement);
if (checkBox.checked == true) {
dragControlsStart();
}
else if (checkBox.checked == false) {
dragControlsStop();
}
}

It looks like the controls have an activate and deactivate function on them that add and remove all the events, which sounds like what you're looking for:
// create drag controls once and activate or deactivate
const dragControls = new THREE.DragControls(meshes, camera, renderer.domElement);
function dragAndDropActivate() {
let checkBox = document.getElementById("dragAndDropCheckbox");
if (checkBox.checked == true) {
dragControls.activate();
}
else if (checkBox.checked == false) {
dragControls.deactivate();
}
}
Another thing to note in your code is that the way you are adding and removing events will not work in Javascript because you are creating new function handles every time you call those functions. Instead you want to create a function once and use the same reference when adding or removing listeners.
function dragEndCallback(event) {
// ...
}
dragControls.addEventListener('dragEnd', dragEndCallback);
dragControls.removeEventListener('dragEnd', dragEndCallback);
Hope that helps!

Solution:
let dragControls = new THREE.DragControls(ArrayOfMesh, camera, renderer.domElement);
dragControls.addEventListener('dragstart', function (event) {
controls.enabled = false;
});
dragControls.addEventListener('dragend', function (event) {
controls.enabled = true;
});
dragControls.deactivate();
function dragAndDropActivate() {
let checkBox = document.getElementById("dragAndDropCheckbox");
if (checkBox.checked == true) {
dragControls.activate();
}
else if (checkBox.checked == false) {
dragControls.deactivate();
}
}

Related

Tracking down webGL crash reason - possible video memory leak

I am creating new AnimatedSprites on pointerdown event (and deleting them on next pointerdown event) over the course if application lifetime. At some point around 20 clicks, the app crashes with an error: Rats! webGl crashed. At that point no error is displayed in console. Crash happens on a mobile device, and would probably also happen on desktop, if someone perform plenty of clicks.
Code that is repeatedly used is below. I also include live example at http://forwardingsolutions.club/. Can someone please point out what am I doing wrong?
From other answers I deduced that you need to reset the loader and call destroy() on animated sprite. I call both of this methods, but there is still an issue.
function setupNextSpritesAnimation(){
setupNextAnimation();
console.log("next color: "+nextColor);
switch (nextColor) {
case "red":
var newLoader = new PIXI.loaders.Loader()
.add('nextSprite', '/assets/sprite/red.png.png')
.load(function (loader, resources){
var interval = setInterval(function(){
if (!isAnimating){
clearInterval(interval);
createNewAnimatedSprite(resources,newLoader);
}
},50);
});
break;
case "aqua":
var newLoader = new PIXI.loaders.Loader()
.add('nextSprite', '/assets/sprite/aqua.png.png')
.load(function (loader, resources){
var interval = setInterval(function(){
if (!isAnimating){
clearInterval(interval);
createNewAnimatedSprite(resources,newLoader);
}
},50);
});
break;
case "green":
var newLoader = new PIXI.loaders.Loader()
.add('nextSprite', '/assets/sprite/blue.png.png')
.load(function (loader, resources){
var interval = setInterval(function(){
if (!isAnimating){
clearInterval(interval);
createNewAnimatedSprite(resources,newLoader);
}
},50);
});
break;
case "purple":
var newLoader = new PIXI.loaders.Loader()
.add('nextSprite', '/assets/sprite/purple.png.png')
.load(function (loader, resources){
var interval = setInterval(function(){
if (!isAnimating){
clearInterval(interval);
createNewAnimatedSprite(resources,newLoader);
}
},50);
});
break;
}
}
function createNewAnimatedSprite(resources,newLoader){
var tmpSprite = new PIXI.extras.AnimatedSprite(setupFrames(resources["nextSprite"].texture.baseTexture));
app.stage.addChild(tmpSprite);
spritesArray.push(tmpSprite);
setupNextSprites(tmpSprite);
app.renderer.plugins.prepare.upload(tmpSprite, function(){
console.log("updoaded now");
canRunNext = true;
newLoader.reset();
//console.log("kill");
delete tmpSprite;
});
}
function setupNextSprites(nextSprite){
nextSprite.x = app.renderer.width / 2;
nextSprite.y = app.renderer.height / 2;
nextSprite.anchor.set(0.5);
nextSprite.loop = false;
nextSprite.animationSpeed = 0.5;
nextSprite.visible = false;
nextSprite.onComplete = function (){
console.log("animation finished");
isAnimating = false;
};
}
function setupNextAnimation(){
var randomNumber = getRandomInt(0,3);
switch (randomNumber) {
case 0:
nextColor = "red";
break;
case 1:
nextColor = "aqua";
break;
case 2:
nextColor = "green";
break;
case 3:
nextColor = "purple";
break;
}
}
app.stage.on("pointerdown", function () {
if (firstRun && !isAnimating) {
firstRun = false;
isAnimating = true;
currentSprite.gotoAndPlay(0);
currentSprite.gotoAndPlay(0);
}else{
if (canRunNext && !isAnimating){
isAnimating=true;
if (currentSprite.visible){
currentSprite.visible = false;
currentSprite.destroy(true);
}
spritesArray[spritesArray.length-1].visible = true;
spritesArray[spritesArray.length-1].gotoAndPlay(0);
app.stage.removeChild(spritesArray[spritesArray.length-2]);
spritesArray[spritesArray.length-2].destroy({ children:true, texture:true, baseTexture:true});
canRunNext = false;
setupNextSpritesAnimation();
}
}
});
function setupSpritesAnimation(){
//created currentSprite just once at the start of app
spritesArray.push(currentSprite);
}

MutationObserver not observing in ie11 after using its disconnect function

My code is as below
var originalTitle = document.title.split("#")[0];
var testtar = document.getElementsByTagName('title')[0];
try{
document.attachEvent('onpropertychange', function (evt) {
console.log('inside attachEvent');
if(evt.propertyName === 'title' && document.title !== originalTitle) {
setTimeout(function () {
document.title = originalTitle;
}, 0);
}
});
}
catch(e){
function disconnect(){
observer.disconnect();
setTimeout(function(){
observer.observe(testtar, config);
console.log(observer)
},1000);
}
var observer = new MutationObserver(function(mutations) {
testtar.innerHTML = originalTitle;
disconnect();
});
var config = { attributes: true, childList: true, characterData: true, characterDataOldValue: true };
observer.observe(testtar, config);
};
I am trying to check for title change using MutationObserver. but once i call observer.disconnect() and again call its observe() method it doesn't work.
the title changes for the second time but still testtar.innerHTML is not set to originalTitle. please help

Checkbox with search filter codeigniter

My problem is when I check one of the checkboxs and then I search it, the checkbox will change to uncheck. and I don`t know what's wrong with my livesearch, it is not working.
please check this link to test.
http://jsfiddle.net/v921/KmVHf/4/
is is my javascript
var tr = $(".AvailableGroupLab").clone().html();
function filter(element) {
$('.AvailableGroupLab').html(tr);
var value = $(element).val().toLowerCase();
$(".AvailableGroupLab tr").each(function () {
if ($(this).text().toLowerCase().search(value) == -1){
$(this).remove();
}
});
}
Try
function filter(element) {
var $trs = $('.AvailableGroupLab tr').hide();
var regexp = new RegExp($(element).val(), 'i');
var $valid = $trs.filter(function () {
return regexp.test($(this).children(':nth-child(2)').text())
}).show();
$trs.not($valid).hide()
}
$('input:text').on('keyup change', function () {
filter(this);
})
Demo: Fiddle

How to add a dropdown menu to a firefox addon sdk powered addon toolbar button?

I use the https://github.com/erikvold/toolbarbutton-jplib/ package to add a toolbar button from an addon-sdk addon to the firefox navigation bar. Is it possible to add a drop down menu to this button (as I understand there are no easy ways)?
This is how I do it; hope it works for you.
var winUtils = require("window-utils");
var delegate = {
onTrack: function(window) {
if(window.location != "chrome://browser/content/browser.xul") {
// console.log("=> win location false");
return;
}
console.log("window tracked");
var document = window.document;
var navBar = document.getElementById('nav-bar');
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', 'button');
btn.setAttribute('type', 'menu-button');
btn.setAttribute('class', 'toolbarbutton-1');
btn.setAttribute('image', 'http://www.facebook.com/favicon.ico');
btn.addEventListener('command', function() {
console.log("this=" + this.id);
// your callback code here
}
, false);
var menupopup = document.createElement('menupopup');
menupopup.setAttribute('id', 'menupopup');
menupopup.addEventListener('command', function(event) {
// TODO your callback
}
, false);
//menu items
var menuitem1 = document.createElement('menuitem');
menuitem1.setAttribute('id', 'menuitem1');
menuitem1.setAttribute('label', 'Menu item1');
menuitem1.setAttribute('class', 'menuitem-iconic');
menuitem1.addEventListener('command', function(event) {
// CODE
}
, false);
}
winUtils.WindowTracker(delegate);
This code requires a few more lines to actually work:
var delegate = {
onTrack: function(window) {
if(window.location != "chrome://browser/content/browser.xul") {
// console.log("=> win location false");
return;
}
var document = window.document;
var navBar = document.getElementById('nav-bar');
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', 'button');
btn.setAttribute('type', 'menu-button');
btn.setAttribute('class', 'toolbarbutton-1');
btn.setAttribute('image', 'http://www.facebook.com/favicon.ico');
btn.addEventListener('command', function() {
console.log("this=" + this.id);
// your callback code here
}
, false);
var menupopup = document.createElement('menupopup');
menupopup.setAttribute('id', 'menupopup');
menupopup.addEventListener('command', function(event) {
// TODO your callback
}
, false);
//menu items
var menuitem1 = document.createElement('menuitem');
menuitem1.setAttribute('id', 'menuitem1');
menuitem1.setAttribute('label', 'Menu item1');
menuitem1.setAttribute('class', 'menuitem-iconic');
menuitem1.addEventListener('command', function(event) {
// CODE
}
, false);
menupopup.appendChild(menuitem1);
btn.appendChild(menupopup);
navBar.appendChild(btn);
console.log("window tracked");
}
};
//let utils = require('api-utils/window-utils');
let utils = require('sdk/deprecated/window-utils'); // for new style sdk
utils.WindowTracker(delegate);

How to Fix Poor Performance on Filter By Text

A while back I found some code that allows you to filter the contents of a SELECT by typing in a text element. It works well however, over time the performance degrades pretty badly. I'm not sure if it is the filter code or the way in which I am activating it.
The SELECT shows up in a modal dialog (bootstrap) so I have the following code:
$('#myModal').on('shown', function () {
$(".focusable").val("").focus();
var select = $('#myModal').find(".modal-body").find("select");
var text = $('#myModal').find(".modal-body").find("input[type='text']");
select.filterByText(text, true);
});
And here is the filter code:
jQuery.fn.filterByText = function (textbox, selectSingleMatch) {
return this.each(function () {
var select = this;
var options = [];
$(select).find('option').each(function () {
options.push({value:$(this).val(), text:$(this).text(), data:$(this).data("short-name")});
});
$(select).data('options', options);
$(textbox).bind('change keyup', function () {
var options = $(select).empty().data('options');
var search = $.trim($(this).val());
var regex = new RegExp(search, 'gi');
$.each(options, function (i) {
var option = options[i];
if (option.text.match(regex) !== null) {
var copyOption = $('<option>').text(option.text).val(option.value);
copyOption.data("short-name", option.data);
$(select).append(copyOption);
}
});
if (selectSingleMatch === true &&
$(select).children().length === 1) {
$(select).children().get(0).selected = true;
}
});
});
};
Can anyone shed some light on where my performance issue(s) might be and how to solve it?
reading through the comments I would suggest to add the following:
$(textbox).bind('change keyup', function(event) {
console.log(event);
// your code
});
Is the event triggered more than once on a single keyup after some times the dialog is shown?
$('#myModal').on('hidden', function () {
$('#myModal').find(".modal-body").find("input[type='text']").off("change keyup");
});

Resources