DropEffect semantic for HTML5 drag and drop - html

According to the HTML5 specs the dropEffect property on a drop target allows the drop target to select the desired drop effect. The drag and drop framework should combine this with the effectAllowed property set by the drag source to display the matching visual feedback (typically a specific cursor depending on the operation).
I was however not able to use this feature consistently across browsers. It seems to work for Chrome and Opera as expected but doe not for IE and FF (although the developer documentation for each browsers explicitly documents it).
I have put together a sample on JSFiddle: http://jsfiddle.net/cleue/zT87T/
function onDragStart(element, event) {
var dataTransfer = event.dataTransfer,
effect = element.innerText || element.textContent;
dataTransfer.effectAllowed = effect;
dataTransfer.setData("Text", effect);
dataTransfer.setDragImage(element, 0, 0);
}
function onDragEnter(element, event) {
var dataTransfer = event.dataTransfer,
effect = element.innerText || element.textContent;
dataTransfer.dropEffect = effect;
event.preventDefault();
}
function onDragOver(element, event) {
var dataTransfer = event.dataTransfer,
effect = element.innerText || element.textContent;
dataTransfer.dropEffect = effect;
event.preventDefault();
}
Is this sample incorrect or my understanding of the purpose of this feature or are these browser bugs?

i had exactly the same problem and came to the same conclusion as yourself, it just doesn't work. In addition to changing the mouse cursor there is the job of working out at the source element what took place - from the spec you can listen to dragend and e.g. remove the element if the drop effect was move and leave it if it were copy. That doesn't work consistently either. I asked the question here, i put a longish explanation with all my findings.
btw - i see it says that drag and drop is at risk from being removed due to a lack of implementation which is a pity.

Related

Change the cursor icon in viewer

I am looking to change the cursor in the viewer when I activate my tool in the viewer. I have tried updating the cursor CSS value for the canvas of the viewer but it seems to be overwritten to the default viewer one.
You should show what you've tried.
If you add this css:
.adsk-viewing-viewer > .canvas-wrap > canvas {
cursor: pointer !important;
}
Just replace 'cursor: pointer' with the type of cursor you'd like. Be sure to add the !important value or it won't override the default cursor.
The canvas is generated after the document is ready, so you'd need to wait for the appropriate events if you are looking to override the cursor style with JS.
Edit:
I noticed you said you were activating it from a tool, so to set the cursor like this with js:
const viewerCanvas = document.getElementsByTagName('canvas')[0] //may need to ensure [0] is the viewer canvas if multiple canvas's
viewerCanvas.setAttribute('style', 'cursor: pointer !important');
You just need to unsure that you handle both tool-activated and tool-deactivated toggle events.
Try this to set the cursor style:
viewer.canvas.style.cursor = "pointer" | "progress" ...
And beware that that'd be overwritten again when navigation tools are activated so to stick to a cursor at all times follow the other answer to override by class name in your stylesheet with the !important rule.
As I stumbled across the same problem I found the way other tools implement this behavior:
You can set the cursor by implementing the getCursor function in your tool (your tool must be active and have the highest priority). This seems to be the easiest and safest method to set the mouse cursor. Also note that an cursor image should be 32x32px for best compability according to mozilla.
Look in the OrbitDollyPanTool for an example:
this.getCursor = function ()
{
if (!_useCustomCursors)
return null;
switch (_activeMode) {
case "freeorbit":
case "orbit":
return 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAt1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAzMzP6+vri4uISEhKKioqtra2dnZ2EhIR9fX10dHRkZGQdHR3t7e3Hx8e5ubm1tbWoqKhWVlZKSko4ODgICAjv7+/o6OjMzMyxsbFOTk4pKSkXFxcEBAT29vbW1tZ6enpISEgLCwvhzeX+AAAAGXRSTlMANRO0nHRJHfnskIxQRKh89syDVwTWZjEJxPFEswAAAOFJREFUKM+1j+lygkAQhIflEAJe0Rw9u4CCeKKoSTTX+z9XoMJWWeX+ssrvZ3f19DQ5zOw/0DUMQPlmQ72bE2adBp8/Rp3CQUi3ILx+bxj4fjDs9T1Bmo6bbPPN8aDU4bjJt4nb+de789kSFyxn826jW3ICLNZZKU8nWWbrBTCRVm04U8TpjquRFf1Go0d7l8aYOrUR7FGEFr1S9LGymwthgX2gE/Kl0cHPOtF2xOWZ5QpIC93RflW4InkDoPRXesd5LJIMQPzV7tCMa7f6BvhJL79AVDmYTNQ1NhnxbI/uwB8H5Bjd4zQPBAAAAABJRU5ErkJggg==), auto';
case "dolly":
return "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAgVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8mJiYAAADNzc2/v7+fn59paWlPT08MDAwICAj6+vqpqak7Ozv29vby8vLp6em2traAgIBkZGRZWVlAQEAaGhpISEgkS7tbAAAAFHRSTlMAOvhpZD8mkQWegMy9qY1YVE01EYiqlE0AAADZSURBVCjPbY9ZloMgEAAbEbfsmRZZXbJn7n/AAX2RQVN/VD26AXLOeZLDGo6IbfI9tHq8cdxuj1HwvgCoaiHqKoRk+M3hB9jueUW8PnfsE/bJ3vms7nCkq7NoE3s99AXxoh8vFoXCpknrn5faAuJCenT0xPkYqnxQFJaU0gdZrsKm8aHZrAIffBj40mc1jsTfIJRWegq6opTMvlfqLqYg7kr1ZB7jFgeaMC59N//8O4WZ1IiPF8b5wMHcJn8zB4g4mc77zpxgAbMSUVoGK4iV0hL4wrksz+H0Bw5+E+HrniDQAAAAAElFTkSuQmCC), auto";
case "pan":
return "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABHVBMVEUAAABPTk4AAAAAAAAJCQkRERE0MzQQEBAODg4QEBB4d3dbWlo9PDw/Pj4vLy8sLCwZGBgWFhYcHBwKCgoSEhIAAAAKCgoICAgKCgoQEBAODg4EBAQICAgPDw8REREMDAx2dnY0NDQvLy9QUFAaGhomJSYjIyM7OjokJCQNDA0mJiYNDQ0AAAAUFBQJCQkQEBAEBAQNDQ0PDw8VFRX///+amJkAAAD5+fnz8/PKycn9/f339vbi4eLR0dDNzMyAgIB8e3xycHH7+/vw7+/o6OjX1ta7urq4t7iwsLCnp6eioqKbmppva21OTk74+Pjl5eXc3Nzb29vLy8vDw8PDwsKrqqqdnZ2WlpaSkpKTkZKMiouEg4NkZGRISEgxLzBpgbsEAAAANHRSTlMA+fiQXgngKSYG/vX17uvBuqackpCNg3BpUkpAPBwTDvj18+vl0s/NwrOwoZZ+TDg4NBkBGrzX8QAAAP5JREFUKM99j9Vuw0AQRdeuKZyGkyZNmbnXDLHDVGb8/8/oy7paK1bO0+oc7WiGnGiaxq+QRTQAOh8f9Jv4H/Ge8PZPrCdlvkxfYluUT2WyyCq3mZ7unwlKVLcqOzA/Mf71j0TWJ/Ym6rPeca05Ni4iIevYc7yoUD2zQFhq71BdI9nvBeBabFDSPe8DswlUc1Riw3VxbH0NHBUPQ0jrbDnPYDjALQBMq9E7nkC5y7VDKTZlUg8Q0lmjvl74zlYErgvKa42GPKf3/a0kQmYCDY1SYMDosqMoiWrGwz/uAbNvc/fNon4kXRKGq+PUo2Mb96afV0iUxqGU2s4VBbKUP65NL/LKF+7ZAAAAAElFTkSuQmCC), auto";}
return null;
};

mobile: how to prevent pull-to-refresh

How to prevent pull-to-refresh in web applications for Chrome android?
I tried the answers from
Disabling android's chrome pull-down-to-refresh feature
body {
overflow-y: hidden;
}
or
body {
touch-action: none;
}
It did not work. any one has a solution that works? It is very bad for browsers to make pull-to-refresh default behavior, it is very undesirable for web applications.
Here's a CSS method of capturing the required touch gestures to prevent the pull to refresh:
$("html").css({
"touch-action": "pan-down"
});
This method seems to have worked well for other users. Hope it works for your needs.
Reference, plus there's more strategies discussed here:
Disabling android's chrome pull-down-to-refresh feature
The code below is a javascript-only solution distilled from a couple of sources, which are towards the bottom.
If you are willing to change the structure of your pages, a CSS/HTML only option may work for you.
Additionally, the draft CSS property scroll-boundary-behavior is in the process of being standardized and added to Chrome provide this capability among a few others. As the implementation is very, very new, I provide links at the bottom of my answer.
Example
although jsfiddle's iframe structure prevents pull-to-refresh from working at all, I also tested the same script within a flat HTML document on Chrome Android 60.0.3112.116.
Full jsfiddle
event.preventDefault() can keep browser default behaviors such as pull-to-refresh from taking place. We want the usual browser behavior most of the time, just not when it would lead to a pull-to-refresh. Since a pull-to-refresh happens when touches are moving down the screen and we're scrolled to the top of the document, we'll only call preventDefault under those conditions.
//We're going to make a closure that will handle events
//so as to prevent the pull-to-refresh behavior.
var pullToRefreshPreventer = (function() {
//To determine the direction in which a touch is moving,
//we hold on to a map from touch identifier to touches
//from the previous event.
var previousTouches = {};
return function(event) {
//First we get all touches in this event and set up
//the value which will replace `previousTouches`
//before this event handler exits.
var touches = Array.prototype.slice.call(event.touches);
nextTouches = {}
touches.forEach(function(touch){
nextTouches[touch.identifier] = touch;
});
//Pull-to-refresh behavior only happens if we are
//scrolled to the top of the document, so we can
//exit early if we are somewhere in the middle.
if(document.scrollingElement.scrollTop > 0) {
previousTouches = nextTouches;
return;
}
//Now we know that we are scrolled to the top of
//the document;
//look through the current set of touches and see
//if any of them have moved down the page.
for(var ix = 0; ix < touches.length; ix++) {
var touch = touches[ix],
id = touch.identifier;
//If this touch was captured in a previous event
//and it has moved downwards, we call preventDefault
//to prevent the pull-to-refresh behavior.
if(id in previousTouches && previousTouches[id].screenY < touch.screenY) {
event.preventDefault();
console.log("event.preventDefault() called")
break;
}
}
//lastly, we update previousTouches
previousTouches = nextTouches;
};
}());
//Since touch events which may call `preventDefault` can be
//much more expensive to handle, Chrome disallows such calls
//by default. We must add the options argument `{passive: false}`
//here to make it work.
document.body.addEventListener('touchmove', pullToRefreshPreventer, {passive: false});
document.body.addEventListener('touchend', pullToRefreshPreventer, {passive: false});
References:
StackOverflow answer linking to chromestatus.com page
"Treat Document Level Touch Event Listeners as Passive", chromestatus
"Making touch scrolling fast by default"
"Touch events"
scroll-boundary-behavior links:
chromestatus
chromium bug
github issue proposing the standard
draft css module, last publish date 2017-09-07

How to I disable form autofill in all browsers?

I've looked through a number of posts all pointing towards different ways of using the autocomplete property, but I have yet to have this work in all my browsers. I've seen some really ugly workarounds such as this, but I'm looking for something that is clean and easy.
What is a good way to disable text field autofill on all (or at least, most) common browsers?
The following code will disable autocomplete in FF, IE, and Chrome.
<script>
$(document).ready(function () {
// IE & FF
$('input').attr('autocomplete', 'off');
// Chrome
if ( $.browser.webkit ) {
$('input').attr('autocomplete', 'new-password');
}});
</script>
Enabling Autocomplete on both form and input fields (with the "off" value) for the sake of those law-abiding browsers that do play by the rules is always a good beginning - also for the unlikely event that one day "other" browser...s may feel like compliance isn't all bad.
Until that day hacks are needed. I've noticed that Chrome looks for matching data in at least three places: Labels (contexts), Names and Placeholders. If the Name field is missing from input fields it will look in both Labels and placeholders, but if the Name field is present it will only look in Name and Placeholder.
This script utilize the "form-control" class from Bootstrap on input fields that must be guarded from Autocomplete. Use any other class or filter you like. Also assuming that Placeholders are in use - just remove that part if not.
$(document).ready(function() {
// Begin
var this_obj = null, this_placeholder = null, this_name = null;
$(".form-control").focus(function() {
this_obj = this;
this_name = $(this).prop("name");
this_placeholder = $(this).attr("placeholder");
$(this).prop("name", "NaN" + Math.random());
$(this).attr("placeholder", "...");
}).blur(function() {
$(this_obj).prop("name", this_name);
$(This_obj).attr("placeholder", this_placeholder);
});
// End
});
Note: Leaving the Placeholder empty might actually inadvertently trigger the Autocomplete function as empty assignments are apparently ignored.
The two variables this_name and this_placeholder may be avoided as they are accessible through this_obj, but I like to keep them around for the sake of readability and clarity.
The Script is erm.. quite unobtrusive, as it cleans up after itself and it only requires one matching class or attribute.
It works in Version 68.0.3440.106 (Officiel version) (64-bit), IE11 11.228.17134.0 and Firefox 61.0.2 (64-bit). Sorry, haven't tested others.
Add a class to all your input tags, suppose no-complete
And in your js file add following code:
setTimeout(function (){
$('.no-complete').val ("");
},1);

Strange IE11 form fields bug after selecting from dropdown

I'm experiencing a major bug in IE 11 (latest version 11.0.9600.16521 on Windows 7). When on any form if I open a select dropdown all the other form fields on the page freeze. I can 'unfreeze' them by adjusting the Window size (causing a redraw). This seems to happen on any form what-so-ever.
To reproduce:
Open IE 11.0.9600.16521
Go to http://www.wikipedia.org/
Select any language from the language dropdown
Result:
language dropdown does not appear to get updated on the screen
the search box appears to be frozen - i.e. focus on select box and start typing but no text appears. However if you adjust the window size the form fields are updated and go back to working as normal (until you interact with another select element)
I can't find much in Google for this issue so maybe it's just something specific to my settings. Only thing that sounds somewhat similar to what I'm experiencing is this: http://connect.microsoft.com/IE/feedback/details/806679/ie-11-desktop-selecting-an-item-from-a-drop-down-list-on-a-webpage-causes-the-tab-to-crash. Anyone else able to reproduce this?
I had a similar issue with IE11 that turned out to be any modification to the .text property of an SELECT-option element. I eventually found the "hint" on stackoverflow here
How to fix IE select issue when dynamically changing options.
In my case I use straight JavaScript, and with so many inter-dependent SELECT boxes had to come up with a generic solution, so my solution was to intercept (defineGetter) assignment to any .text property of an HTMLOptionElement, and set a 1 ms timer to perform an add element and remove element as in the referenced post that is titled "I have the fix. We have to add and remove options list to trigger the rendering in IE8." Notice the reference to IE8, AFAIK IE has had several issues with SELECT boxes since at least IE7, possibly earlier.
So the code I added to one of my global scripts is as follows:
try { var IE11; // IE10 and IE11 removed ActiveXObject from the window object but it can still be instantiated
IE11 = new ActiveXObject('MSXML2.DOMDocument.6.0');
IE11 = null;
if (typeof(HTMLOptionElement) != "undefined") {
try { HTMLOptionElement.prototype.__defineSetter__(
'text',
function(original) {
return function(newValue) { var sel;
original.call(this, newValue);
if (!(sel=this.parentElement).fixIE) sel.fixIE = window.setTimeout(_fixIE_(sel), 1);
}
}(HTMLOptionElement.prototype.__lookupSetter__('text')));
} catch(e) {};
}
} catch(e) {}
}
// IE11 broke SELECT boxes again, modifying any options .text attribute "freezes" the SELECT so it appears disabled
function _fixIE_(selBox) {
return _fixIE_;
function _fixIE_(){ var lc = selBox.options.length;
selBox.options.add(new Option('',''));
selBox.options.remove(lc);
selBox.fixIE = undefined;
}
}
Phil
Go to programs
Then widdcom folder
Right click bttray
Go compatibility
Tick run as admin
Restart
I had the same problem in IE 11 on Dell Windows 7.
It was solved by turning off hardware rendering in IE, as you suggested in your link.

mootools - using addEvent to element not working properly?

bangin' my head against this and it's starting to hurt.
I'm having trouble with adding an event to an element.
I'm able to add the event, and then call it immediately with element.fireEvent('click'), but once the element is attached to the DOM, it does not react to the click.
example code:
var el = new Element('strong').setStyle('cursor','pointer');
el.addEvent('click',function () { alert('hi!'); });
el.replaces(old_element); // you can assume old_element exists
el.fireEvent('click'); // alert fires
however, once I attach this to the DOM, the element is not reactive to the click. styles stick (cursor is pointer when I mouseover), but no event fires. tried mouseover as well, to no avail.
any clues here? am I missing something basic? I am doing this all over the place, but in this one instance it doesn't work.
EDIT----------------
ok here's some more code. unfortunately I can't expose the real code, as it's for a project that is still under tight wraps.
basically, the nodes all get picked up as "replaceable", then the json found in the rel="" attribute sets the stage for what it should be replaced by. In this particular instance, the replaced element is a user name that should pop up some info when clicked.
again, if I fire the event directly after attaching it, all is good, but the element does not react to the click once it's attached.
HTML-----------
<p>Example: <span class='_mootpl_' rel="{'text':'foo','tag':'strong','event':'click','action':'MyAction','params':{'var1': 'val1','var2': 'val2'}}"></span></p>
JAVASCRIPT-----
assumptions:
1. below two functions are part of a larger class
2. ROOTELEMENT is set at initialize()
3. MyAction is defined before any parsing takes place (and is properly handled on the .fireEvent() test)
parseTemplate: function() {
this.ROOTELEMENT.getElements('span._mootpl_').each(function(el) {
var _c = JSON.decode(el.get('rel'));
var new_el = this.get_replace_element(_c); // sets up the base element
if (_c.hasOwnProperty('event')) {
new_el = this.attach_event(new_el, _c);
}
});
},
attach_event: function(el, _c) {
el.store(_c.event+'-action',_c.action);
el.store('params',_c.params);
el.addEvent(_c.event, function() {
eval(this.retrieve('click-action') + '(this);');
}).setStyle('cursor','pointer');
return el;
},
Works just fine. Test case: http://jsfiddle.net/2GX66/
debugging this is not easy when you lack content / DOM.
first - do you use event delegation or have event handlers on a parent / the parent element that do event.stop()?
if so, replace with event.preventDefault()
second thing to do. do not replace an element but put it somewhere else in the DOM - like document.body's first node and see if it works there.
if it does work elsewhere, see #1
though I realsie you said 'example code', you should write this as:
new Element('strong', {
styles: {
cursor: "pointer"
},
events: {
click: function(event) {
console.log("hi");
}
}
}).replaces(old_element);
no point in doing 3 separate statements and saving a reference if you are not going to reuse it. you really ought to show the ACTUAL code if you need advice, though. in this snippet you don't even set content text so the element won't show if it's inline. could it be a styling issue, what is the display on the element, inline? inline-block?
can you assign it a class that changes it on a :hover pseudo and see it do it? mind you, you say the cursor sticks which means you can mouseover it - hence css works. this also eliminates the possibility of having any element shims above it / transparent els that can prevent the event from bubbling.
finally. assign it an id in the making. assign the event to a parent element via:
parentEl.addEvent("click:relay(strong#idhere)", fn);
and see if it works that way (you need Element.delegate from mootools-more)
good luck, gotta love the weird problems - makes our job worth doing. it wouldn't be the worst thing to post a url or JSFIDDLE too...