`
if (sInd === dInd) {
const reorderCardItems = reorderCard(items[sInd], source.index, destination.index);
const newState = [...items];
newState[sInd].card = reorderCardItems;
seState({newState: newState});
`
if (sInd === dInd) {
const reorderCardItems = reorderCard(items[sInd], source.index, destination.index);
let newState = [...items];
newState[sInd].card = reorderCardItems;
newState= newState;
it's giving me error that 'newState' is assigned to itself.
here is the code:
const [expression, setExpression] = useState("");
const Remove = () => {
const input = document.getElementById("input");
if (expression.length > 0) {
const pos = input.selectionStart;
if (pos > 0) {
setExpression(expression.substring(0, pos - 1) + expression.substring(pos));
input.focus();
input.selectionStart = pos - 1;
input.selectionEnd = pos - 1;
}
}
}
return (
<>
<input id="input" value={expression} />
<button onClick={Remove}>remove</button>
</>
)
I want to remove the text where cursor is place in input box on button click but the cursor goes again and again at the end of input text after removing the number. I want it to stay where it is placed in input field and not go at the end of input box text.
You can do it in a stateful and stateless way.
Stateful
const [expression, setExpression] = useState("");
const [cursorPos, setCursorPos] = useState(0);
useEffect(() => {
const input = document.getElementById("input");
input.focus();
input.setSelectionRange(cursorPos, cursorPos);
}, [cursorPos, expression]);
const handleInput = (e) => {
setExpression(e.target.value);
const input = document.getElementById("input");
setCursorPos(input.selectionStart);
}
const Remove = () => {
const input = document.getElementById("input");
if (expression.length > 0) {
const pos = input.selectionStart;
if (pos > 0) {
setExpression(
expression.substring(0, pos - 1) + expression.substring(pos)
);
setCursorPos(pos - 1);
}
}
};
return (
<>
<input id="input" value={expression} onInput={handleInput} />
<button onClick={Remove}>remove</button>
</>
);
Stateless, using ref
const inputRef = useRef();
const Remove = () => {
const input = inputRef.current;
const value = input.value;
if (value.length > 0) {
const pos = input.selectionStart;
if (pos > 0) {
input.value = value.substring(0, pos - 1) + value.substring(pos);
input.focus();
input.selectionStart = pos - 1;
input.selectionEnd = pos - 1;
}
}
};
return (
<>
<input id="input" ref={inputRef} />
<button onClick={Remove}>remove</button>
</>
);
Using the query string URLSearchparams and consolidating my fetch requests into the Promise.all method, my code is now able to print the elements that I want in the console.log. However, I'm having a hard time getting that information to display in html. It returns "undefined" on the screen but the console.log shows the correct data. What's missing ?
async function loadData() {
const queryStr_id = window.location.search;
console.log(queryStr_id);
const product = new URLSearchParams(queryStr_id);
console.log(product);
const id = product.get("_id");
console.log(id);
try {
const url_teddies = "http://localhost:3000/api/teddies/" + id;
const url_cameras = "http://localhost:3000/api/cameras/" + id;
const url_furniture = "http://localhost:3000/api/furniture/" + id;
const results = await Promise.all([fetch(url_teddies), fetch(url_cameras), fetch(url_furniture)]);
const dataPromises = results.map((result) => result.json());
const finalData = await Promise.all(dataPromises);
console.log(finalData);
for (i = 0; i < finalData.length; i++) {
const prodImg = finalData[i].imageUrl;
const prodName = finalData[i].name;
const prodPrice = finalData[i].price / 100 + " Eur";
const prodDesc = finalData[i].description;
const coloris = finalData[i].colors;
const lenses = finalData[i].lenses;
const varnish = finalData[i].varnish;
console.log(prodImg);
console.log(prodName);
console.log(prodPrice);
console.log(prodDesc);
console.log(coloris);
console.log(lenses);
console.log(varnish);
const productDetails = `
<div class="produit__card__wrapper">
<div class="produit__card__content">
<img src="${finalData[i].imageUrl}" alt="${finalData[i].name}" class="productImg"></img>
<div class="container_text">
<h1 class="name"><span>${finalData[i].name}</span></h1>
<p class="price"><strong>Price : </strong><span>${finalData[i].price / 100 + " €"}</span></p>
<p class="description"><strong>Description : </strong><span>${finalData[i].description}</span></p>
<form>
<label for="product_color"></label>
<select name="product_color" id="product_color">
</select>
</form>
<button id="addToCart" type="submit " name="addToCart">Ajouter au panier</button>
</div>
</div>
</div>
`;
const container = document.querySelector(".container");
container.innerHTML = productDetails;
}
return finalData;
} catch (err) {
console.log(err);
}
}
loadData()
I think you just forgot to flatten your three promised arrays before assigning them to finalData. Try
const finalData = (await Promise.all(dataPromises)).reduce((data, arr) => data.concat(arr), []);
Not the file, I want just drag the image with drag and drop.
I thought I would do it according to the extension of the picture but
I have no idea how to do it
example:
*ngIf="list.file.name.split('.').pop() == 'png'"
Can you tell me if there's another way? can you tell us how?
html code:
<div method="post" >
<div (drop)="ondrop($event)" (dragover)="ondragover($event)" (dragend)="ondragend($event)" id="holder1">
<div class="scrollbar style-1">
<div id="fileDragName" class="input-div-image">
<input name="dragAndDrop" (change)="handleFileSelect($event)" id="filesMain" type="file" required="required" multiple="multiple" />
<h3 class="yazi"> Drag and drop or <h3 class="turuncu-renk"> selected file </h3>
</h3>
<li *ngFor="let list of deneme; let i = index">
<div >
{{list.file.name.split('.').slice(0, -1).join('.')}}
</div>
<div id="progress" class="progress-style" >
<p-progressBar *ngIf="list.progressDurumu" [value]="list.percantage"></p-progressBar>
</div>
</div>
</li>
</div>
</div>
</div>
</div>
.ts code:
ondragover(ev) {
const holder = document.getElementById('holder1');
holder.className = 'hover'
return false;
}
ondragend(ev) {
const holder = document.getElementById('holder1');
holder.className = ''
return false;
}
ondrop(e) {
const holder = document.getElementById('holder1');
holder.className = ''
e.preventDefault();
this.readfiles(e.dataTransfer.files);
this.imageUpload();
}
readfiles(files) {
this.files = files;
}
handleFileSelect(evt) {
this.files = evt.target.files;
this.imageUpload();
}
imageUpload() {
setTimeout(() => {
this.progress.percentage = 0;
this.sonuc = this.files;
for (let i = 0; i < this.sonuc.length; i++) {
this.deneme.push({file: this.sonuc[i] , percantage: 0 , output: null });
this.currentFileUpload = this.sonuc[i];
const reader = new FileReader();
reader.onload = (event: any) => {
this.deneme[this.deneme.length - this.sonuc.length + i].output = event.target.result;
};
reader.readAsDataURL(this.sonuc[i]);
this.userService.imageCreate(this.currentFileUpload).subscribe(event => {
if (event.type === HttpEventType.UploadProgress ) {
this.deneme[this.deneme.length - this.sonuc.length + i].percantage = Math.round(event.loaded / event.total * 100 );
} else if (event instanceof HttpResponse ) {
setTimeout(() => {
this.deneme[this.deneme.length - this.sonuc.length + i].progressDurumu = false;
console.log('Upload images!');
}, 500); }
});
}
}, 51);
}
I have a problem with changes of material of some elements
when geometry is loaded:
_this.viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, () => {
changeModelMaterial()
});
...
const changeModelMaterial = () => {
const grey = new THREE.Color(0.5, 0.5, 0.5);
let dbIds = getDbIds()
changeAllElementsMaterial(grey)
setMaterialOfDbIds(dbIds)
}
code that i`m using to change material:
const changeAllElementsMaterial = (color) => {
const fragmentList = _this.viewer.model.getFragmentList();
for (let materialId of fragmentList.materialids) {
if (fragmentList.materialmap[materialId]) {
fragmentList.materialmap[materialId].map = null
fragmentList.materialmap[materialId].color = color
fragmentList.materialmap[materialId].needsUpdate = true;
}
}
_this.viewer.impl.invalidate(true);
}
const setMaterialOfDbIds = (dbIds) => {
var color_diffuse = 0xAB00EE;
var color_specular = 0xEEABEE;
var colorM = new THREE.MeshPhongMaterial({
color: color_diffuse,
specular: color_specular
});
_this.viewer.impl.matman().addMaterial(
'ADN-Material-' +
"common color material", // or a GUID
colorM,
true);
for (let dbId of dbIds) {
_this.viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
_this.viewer.model.getFragmentList().setMaterial(fragId, colorM);
});
}
_this.viewer.impl.invalidate(true);
}
It works, because I see that materials of model are changed, but the problem is that materials back to default after ~1-2 sec.
After this I cannot change material even with run this code manually.
Question is why Viewer is locking material change after this 2 sec, how to prevent it
And maybe you will be able to tell me what i can do better with material changes, eg. maybe something better that running my code after GEOMETRY_LOAD. The best would be change material before first render of model
........
hint:
when change event from GEOMETRY_LOADED_EVENT to OBJECT_TREE_CREATED_EVENT "sometimes" but only sometimes it works well (materials stay to the end of working with model), but mostly when i run my method after OBJECT_TREE_CREATED it not working (even not working by run it manually, materials are in some way locked). So I suspect that problem is between time of GEOMETRY_LOAD and OBJECT_TREE_CREATED
I will be grateful for any help
==============================full code==============================
index.html
<div id="main">
<div id="MyViewerDiv"></div>
<button id="open-nav-button" onClick="showDocInfo()">test</button>
</div>
<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/three.min.js"></script>
<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/viewer3D.min.js"></script>
<script type="text/javascript" src="lib/jquery.min.js"></script>
<script src="js/autodesk-viewer.js"></script>
<script src="js/extension/test-extension.js"></script>
<script>
const autodeskViewer = new AutodeskViewer()
const showDocInfo = () => {
autodeskViewer.showDocInfo()
}
</script>
autodesk-viewer.js
var AutodeskViewer = (function () {
function AutodeskViewer() {
var _this = this;
this.urn = 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6Zm9yZ2UtamF2YS1zYW1wbGUtYXBwLTFzcGduazdqcWpxdjhmYXV0YmNzd2R0cGdvN3VtNWY1L1BPQy1Gb3JnZS1JVCUyMDIwMTclMjBSdWNoXzEwMDUxNy5ud2Q';
this.initializeViewer = function (containerId, documentId) {
_this.viewerApp = new Autodesk.Viewing.ViewingApplication(containerId);
var config = {
extensions: ['TestExtension']
};
_this.viewerApp.registerViewer(_this.viewerApp.k3D, Autodesk.Viewing.Private.GuiViewer3D, config);
_this.viewerApp.loadDocument(documentId, _this.onDocumentLoadSuccess, _this.onDocumentLoadFailure);
}
this.onDocumentLoadSuccess = function (doc) {
const viewables = _this.viewerApp.bubble.search(av.BubbleNode.MODEL_NODE);
if (viewables.length === 0) {
return;
}
_this.viewerApp.selectItem(viewables[0].data, _this.onItemLoadSuccess, _this.onItemLoadFail);
_this.viewer3d = _this.viewerApp.getCurrentViewer();
}
this.onDocumentLoadFailure = (viewerErrorCode) => {}
this.onItemLoadSuccess = (viewer) => {
_this.viewer = viewer
}
this.onItemLoadFail = (errorCode) => {}
this.initialize = () => {
var options = {
env: 'AutodeskProduction',
getAccessToken: _this.getToken,
refreshToken: _this.getToken
};
Autodesk.Viewing.Initializer(options, _this.initCallback);
};
this.initCallback = function () {
_this.initializeViewer('MyViewerDiv', _this.urn, '3d');
};
this.getToken = function (onGetAccessToken) {
$.get("forge/oauth/token")
.done(function (data) {
token = data
onGetAccessToken(token, 60 * 60);
})
.fail(function (error) {
console.log('ERROR', error);
});
};
this.showDocInfo = function () {};
this.initialize();
}
return AutodeskViewer;
}());
test-extension.js
var _self;
var _viewer;
var _tempValue = 0;
function TestExtension(viewer, options) {
Autodesk.Viewing.Extension.call(this, viewer, options);
_self = this;
_viewer = viewer;
}
const changeModelMaterial = () => {
// _tempValue++;
// if (_tempValue == 2) {
const elements = [4340, 4342, 4344, 4346, 4348, 4367, 4371, 4375, 4380, 4452, 4468, 4488, 4503, 4517, 4520, 4522, 4524, 4526, 4528, 4530]
changeAllElementsMaterial(new THREE.Color(0.5, 0.5, 0.5))
setMaterialOfDbIds(elements)
_tempValue = 0
// }
}
const changeAllElementsMaterial = (color) => {
var fragmentList = _viewer.model.getFragmentList();
for (let materialId of fragmentList.materialids) {
if (fragmentList.materialmap[materialId]) {
fragmentList.materialmap[materialId].map = null
fragmentList.materialmap[materialId].color = color
fragmentList.materialmap[materialId].needsUpdate = true;
}
}
_viewer.impl.invalidate(true);
}
const setMaterialOfDbIds = (dbIds) => {
var colorM = new THREE.MeshPhongMaterial({
color: new THREE.Color(0xAB00EE)
});
for (let dbId of dbIds) {
_viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
_viewer.model.getFragmentList().setMaterial(fragId, colorM);
});
}
_viewer.impl.invalidate(true);
}
TestExtension.prototype = Object.create(Autodesk.Viewing.Extension.prototype);
TestExtension.prototype.constructor = TestExtension;
TestExtension.prototype.load = function () {
_viewer.addEventListener(Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, changeModelMaterial)
// _viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, changeModelMaterial)
return true
};
TestExtension.prototype.unload = function () {
return true
};
Autodesk.Viewing.theExtensionManager.registerExtension('TestExtension', TestExtension);
I found the solution, quite accidentally... from other thing i tried to do
before:
const setMaterialOfDbIds = (dbIds) => {
var color_diffuse = 0xAB00EE;
var color_specular = 0xEEABEE;
var colorM = new THREE.MeshPhongMaterial({
color: color_diffuse,
specular: color_specular
});
_this.viewer.impl.matman().addMaterial("common color material", colorM, true);
for (let dbId of dbIds) {
_this.viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
_this.viewer.model.getFragmentList().setMaterial(fragId, colorM);
});
}
_this.viewer.impl.invalidate(true);
}
after
const setMaterialOfDbIds = (dbIds) => {
var color_diffuse = 0xAB00EE;
var color_specular = 0xEEABEE;
var colorM = new THREE.MeshPhongMaterial({
color: color_diffuse,
specular: color_specular
});
_this.viewer.impl.matman().addMaterial("common color material", colorM, true);
for (let dbId of dbIds) {
_this.viewer.model.getData().instanceTree.enumNodeFragments(dbId, function (fragId) {
_this.viewer.model.getFragmentList().setMaterial(fragId, colorM);
var fragProxy = _this.viewer.impl.getFragmentProxy(_this.viewer.model, fragId)
fragProxy.updateAnimTransform()
});
}
_this.viewer.impl.invalidate(true);
}
Really I don`t know why adding
var fragProxy = _this.viewer.impl.getFragmentProxy(_this.viewer.model, fragId)
fragProxy.updateAnimTransform()
made the difference, i didn`t saw anything like that in any example of updating material.
What is interesting this code is running for only few elements in model, but it works for even those elements that materials changed before (in changeAllElementsMaterial method).
#Philippe Leefsma if you understand it pls tell something more why it works
So far I cannot reproduce the issue on my side, I am using the following code (ES7) extracted from that extension: Viewing.Extension.Material
createColorMaterial (color) {
const material = new THREE.MeshPhongMaterial({
specular: new THREE.Color(color),
side: THREE.DoubleSide,
reflectivity: 0.0,
color
})
const materials = this.viewer.impl.getMaterials()
materials.addMaterial(
this.guid(),
material,
true)
return material
}
async onModelCompletedLoad() {
const material = this.createColorMaterial(0xFF0000)
const model = this.viewer.model
const fragIds = await Toolkit.getFragIds(model)
fragIds.forEach((fragId) => {
model.getFragmentList().setMaterial(
fragId, material)
})
this.viewer.impl.sceneUpdated(true)
}
The onModelCompletedLoad is a custom event fired when both GEOMETRY_LOADED_EVENT and OBJECT_TREE_CREATED_EVENT have been fired.
Take a look at this article for more details: Asynchronous viewer events notification
I doubt you can easily change the materials before the model is first rendered, however you could use a custom overlay that hides the model until your custom logic has performed all required steps, this is the approach I am using in my demos at: https://forge-rcdb.autodesk.io/configurator
After loading a model, all custom materials are being persisted fine:
The material extension can be tested live from there.
Hope that helps