So I've been cannibalizing this code from this YUI 3 Drag n' Drop tutorial, and it's been working great.
The one issue that I'm running into is that the example code only copies a few of the CSS styles (individually). This also doesn't include styling of any children elements that may be present.
Y.DD.DDM.on('drag:start', function(e) {
var drag = e.target;
drag.get('dragNode').set('innerHTML', drag.get('node').get('innerHTML'));
drag.get('dragNode').setStyles({
opacity: '.5',
borderColor: drag.get('node').getStyle('borderColor'),
backgroundColor: drag.get('node').getStyle('backgroundColor')
});
});
So when the drag starts, we create a dragNode and set its HTML based on the item being dragged. After the dragNode HTML is set, we then set the styles using .setStyles() which seems to accept an object.
Is there a more effective way of creating this dragNode so that it not only gets the correct HTML, but also gets all the styles of the element and its children?
I know I could use .one() or .all() to get to the children elements and manually copy over each style that is set, but I feel like there has to be a way of doing that without all the manual style copying.
You could look at using the DOM cloneNode(true) method to clone the whole thing, which should pull over any applied styles too. One warning with this method (and probably the existing copy of HTML) is that IDs will be duplicated. It's probably ok in the case of populating the Drag Node, which you can't interact with much.
Another possibility which I've not investigated beyond a little googling is to use html2canvas to create an image to drag. I've no idea whether that approach will be performant or accurate enough though.
What I ended up finding out was that I was missing a top-level class (which applied the styling to its children elements).
The fix was surprisingly easy in my case, since I had to only add a single class based on if the element had a specific class or not.
Y.DD.DDM.on('drag:start', function(e) {
var drag = e.target;
drag.get('dragNode').set('innerHTML', drag.get('node').get('innerHTML'));
if( drag.get('node').hasClass('policy') ) {
drag.get('dragNode').addClass('policy');
} else {
drag.get('dragNode').addClass('lead');
}
drag.get('dragNode').setStyles({
opacity: '.5',
borderColor: drag.get('node').getStyle('borderColor'),
backgroundColor: drag.get('node').getStyle('backgroundColor')
});
});
Related
We're trying to visualize an IFC model with forge that contains a lot of invisible elements.
One problem we're facing is that the elements that is invisible does not fall under the normal category of hidden elements. E.g. model.setAllVisibility(true) does not make them appear. Also, model.visibilityManager.hiddenNodes is empty and model.visibilityManager.setVisibilityOnNode(dbId, true) does nothing to make them appear.
What seems to be the case with these elements is that their material.opacity is 0.
We tried setting the opacity to 1, and also tried using a different material, with no luck.
The only thing we have managed to do so far is to highlight the element's corresponding fragment:
model.setHighlighted(fragId, true)
however, this does not really cut it (unless it's possible to highlight many elements, and make them transparent?).
It's also worth mentioning that:
The elements comes from a IfcBuildingElementProxy IFC type
Calling viewer.setDisplayEdges(true) makes it possible to see the wireframe of the invisible elements
It's possible to click on the elements even though they are invisible.
So, my questions:
Is there any good way to find all the invisible elements in a model?
Is it possible to change them to be visible without highlighting them?
The viewer doesn't provide any solution for this out-of-the-box but it should be quite straightforward by putting together some of the viewer's features:
To check the opacity of all objects, you can just get the list of all fragments, and check the opacity of each material:
const frags = viewer.model.getFragmentList();
for (let i = 0; i < frags.getCount(); i++) {
const mat = frags.getMaterial(i);
console.log(mat.opacity);
}
And then, when you find materials you would like to change, you can do that, too. Here's some resources that might help:
how to add custom material to a fragment in forge viewer
https://forge.autodesk.com/blog/material-swatches-forge-viewer
https://forge.autodesk.com/blog/custom-shader-materials-forge-viewer
How can I go about creating a form which pops up when the user clicks a button on a Jade template? I tried the following in HTML, which works:
http://www.formget.com/how-to-create-pop-up-contact-form-using-javascript/
Now to use this in my Node.js project would I need to create a separate Jade file for the form itself? That is what I tried and then I tried to display the form like this:
function div_show() {
alert("Test");
document.getElementById('abc').style.display = "block";
}
Unfortunately that does not work. What is the recommended approach for creating a pop up form in Jade? I am really confused with Jade and I can't seem to find a good tutorial for this, there are loads for HTML...
Thanks for the help!
Normally for this you would use:document.getElementById('abc').style.visibility="visible";
To hide your table use:document.getElementById('abc').style.visibility="hidden";
When using the 'style' attribute you are using plain css commands. Make sure your default div style settings have it 'hidden', if that is what you want.This display:block;visibility:hidden;' must exist in your default settings for that div style so the DOM has a clear path to what it is controlling. By itself 'display:block;' does not hide or make objects visible, it is mostly about the shape the div creates as a container for objects.
As an option you can use:
document.getElementById('abc').style.display="block";
To hide your table use:document.getElementById('abc').style.display="none";
For this you would set your div style settings to 'display:none;visibility:visible;.
In this case 'display="none"' removes the object from all display layers and could allow other objects to fill in it's space. When it is visible it will push other objects on the same z-index out of the way. If it has a higher z-index, say +100 higher, it will pop-up above the other objects on the page. The 'visibility' attribute only controls the objects visibility, it does not remove it from the display memory. It can still take up space even though it is not visible. The 'opacity' attribute does about the same thing, except it allows you to also make an object as transparent as you like.
I have a question regarding this page of mine. The menus and submenus are toggled, and I'm using Isotope. I'd like to know if it's possisble to change the style of the link which just got clicked. Since this is all happening in one page, other solutions for this problem don't work.
I can't get this to work either, probably because I have to use multiple toggles. (+ There is the added complexity of my tv schedule page, since it's basicly an entire page inside a toggle.)
I hope someone can help me by taking a look at my source code.
Create a css class for your active style instead of the inline style you have currently on "TV Schedule" (background: teal; color: white). Call the class "active" for example.
Simply add and remove this class within your click handler you already have setup with jquery. So at 134 in your source:
$('.sort a').click(function(){
//add these 2 lines
$('.sort a').removeClass('active');
$(this).addClass('active');
//the rest of your handler
var selector = $(this).attr('data-filter');
$container.isotope({
filter: selector,
animationOptions: {
duration: 750,
easing: 'linear',
queue: false,
}
});
return false;
});
The first line goes through and removes it from all the a tags in that block if it exists. The next one adds it to the one that was clicked.
That's usually the way I do this sort of thing. It's independent of isotope - just using the jquery you already have in there.
I'd like to create a <video> element within my DOM, and then move it to another position without interrupting the playing of that content.
Perhaps more broadly, is it possible to move any DOM element without disrupting attached events?
Some approaches include using CSS absolute positioning, but is there a way to actually update the DOM in a way that doesn't interrupt the playback?
Unfortunately not. The DOM doesn't really have a concept of move, you just have to detach and reattach. As soon as the DOM node is no longer rooted in a document, it loses its playing state.
You may be able to preserve it somewhat by storing it in JS and re-applying it, but that will probably introduce a little skipping.
As per a workaround, here's the code snippet that worked for me:
function beforeDOMMove() {
if (video.paused) {
const currentTime = video.currentTime
const canPlayListener = () => {
video.removeEventListener('canplay', canPlayListener)
video.currentTime = currentTime
video.play()
}
video.addEventListener('canplay', canPlayListener)
}
}
Can anyone explain why the click handler is not invoked consistently in this example?
http://jsfiddle.net/4QBnf/
For instance, if you click in the upper left half of the div, it does not reliably increment the counter.
If I remove the padding-top from this block it works just fine:
.click-check:active {
background-color:blue;
padding-top: 25px;
}
I have tested this in a number of different browsers and it behaves the same way.
I found two possible issues with your code. You can view the fixes here:
http://jsfiddle.net/4QBnf/6/
CSS Box Model vs jQuery Box Model
Whenever you click on the top half of your box, you aren't technically clicking on .click-check, you are actually clicking on .count. This image shows the location of .count relative to .click-check:
jQuery counts this as a click on .click-check, but CSS doesn't. The number increments, but the CSS "active" effect isn't applied.
You can resolve this by removing the .count div and placing everything inside of .click-check.
jQuery Counter
The second issue is with your jQuery code. The code currrently reads:
$('.click-check').click(function() { $('.count').html(count++); });
count isn't increased until after this line is done. This means that the first click appears to have no effect.
This line will increment count, then display it to the user:
$('.click-check').click(function() { $('.click-check').html(++count); });
I've applied both updates to your example here:
http://jsfiddle.net/4QBnf/6/
Update
An alternate way to resolve the issue is to do everything through jQuery. This synchronizes all of the appearance and logic into a single box-model interpretation.
var count=0;
$('.click-check').mousedown(function() {
$('.click-check').addClass("active");
$('.click-check').html(++count);
setTimeout(function(){
$('.click-check').removeClass("active");
}, 50);
});
http://jsfiddle.net/4QBnf/15/