Turn off the perpetual active mode

I have a situation where a link maintains its active state after being dragged and released. This is causing an issue that I need to address.

For example, you can see the problem here: http://jsfiddle.net/Ek43k/3/

<a href="javascript:void(0);" id="foo" >Drag me</a>

To fix this issue in Internet Explorer and Firefox, I am trying to figure out how to prevent the link from staying in its active state after being dragged and released. Any suggestions on how to achieve this?

Answer №1

This bug has been identified in Firefox and detailed information can be found at https://bugzilla.mozilla.org/show_bug.cgi?id=193321

The bug has shown inconsistent behavior with various reports, indicating a non-standard and browser-specific issue.

An effective workaround involves utilizing JavaScript to address the problem. However, direct influence on pseudo-selector states is limited unless operating in privileged mode (e.g., within an extension). As a result, adding or removing a class name is recommended:

<a href="#" onmousedown="this.className = '';" ondragend="this.className = 'inactive';" id="foo" >Drag me</a>

Experiment with this method using: http://jsfiddle.net/frsRS/

If operating in privileged mode, consider employing the technique utilized by Firebug's CSS Panel using inIDOMUtils.setContentState

var node = document.getElementById("foo");
var domUtil = Components.classes["@mozilla.org/inspector/dom-utils;1"].getService(Components.interfaces.inIDOMUtils);
domUtil.setContentState(node, 1);

Edit

A more advanced implementation for binding cross-browser delegates instead of inline JavaScript (demonstrative purpose only) is provided below:

function addEvent(ele, evnt, funct) {
  if (ele.addEventListener) // W3C
    return ele.addEventListener(evnt,funct,false);
  else if (ele.attachEvent)  // IE
    return ele.attachEvent("on"+evnt,funct);
}
addEvent(document.body, 'mousedown', function (e) {        
    if(e.target.tagName == 'A') e.target.style.color = '';
});
addEvent(document.body, 'dragend', function (e) {
    if(e.target.tagName == 'A') e.target.style.color = 'blue';
});

Try it here: http://jsfiddle.net/HYJCQ/

Incorporating the element's style rather than a CSS class allows flexibility for alternative approaches.

Another strategy, proposed by Supr, involves removing and re-adding elements from the DOM immediately. This can be achieved through delegation as demonstrated here:

function addEvent(ele, evnt, funct) {
  if (ele.addEventListener) // W3C
    return ele.addEventListener(evnt,funct,false);
  else if (ele.attachEvent)  // IE
    return ele.attachEvent("on"+evnt,funct);
}
addEvent(document.body, 'dragend', function (e) {
    if(e.target.tagName != 'A') return;
    var parent = e.target.parentNode;
    var sib = e.target.nextSibling;
    parent.insertBefore(
        parent.removeChild(e.target),
        sib
    );
});

Test this method here: http://jsfiddle.net/ymPfH/

Both delegate-based techniques offer improved efficiency compared to looping through elements, enabling dynamic application to any a tags added post-load similar to jQuery's live or on methods.

Documentation

Answer №2

Unhook and hook back the link in the DOM tree to deactivate its active state. Perform this action when the dragging operation concludes and you've successfully accomplished it:

$('a').on('dragend',function(){
    var $this   = $(this),
        $parent = $this.parent(),
        $next   = $(this.nextSibling); // $.next() doesn't include text
    $this.detach().insertBefore($next);     
});

You don't need to modify your HTML or CSS or remove the :active pseudo-class. This method appears to function correctly in both Firefox and Internet Explorer.


Note: My experience with pure Javascript for DOM manipulation is limited, so the quality might not be perfect, but here is the code without jQuery available at this link:

(function(){
    var previousOnload = window.onload || function noop(){};

    window.onload = function (){

        // Execute any previously defined onload callbacks
        previousOnload();

        // Attach deactivator to each <a> element
        var elements = document.getElementsByTagName('a');
        for (var i=0; i<elements.length; i++){
            elements[i].ondragend = deactivate;
        }

        function deactivate(){
            var parent   = this.parentNode,
                position = this.nextSibling;
            parent.removeChild(this);
            // Using insertBefore instead of appendChild ensures correct positioning among siblings
            parent.insertBefore(this, position);
        }
    };

})();

I addressed some potential issues to make it easy to implement. Tested in Opera, Chrome, Firefox, and Internet Explorer.


Update: Building on Chris' suggestion, another approach to implement the fix is by directly using the ondragend attribute to trigger the deactivate function (not verified):

<head>
    <script>
        function deactivate(){
            var parent   = this.parentNode,
                position = this.nextSibling;
            parent.removeChild(this);
            // Use insertBefore instead of appendChild for accurate sibling placement
            parent.insertBefore(this, position);
        }
    </script>
</head>
<body>
    <a href="#" ondragend="deactivate()">Drag me</a>
<body>

The downside is that each link needs the ondragend attribute specified alongside the javascript function manually. It's a matter of personal preference.


Final (?) Update: Refer to the comments for delegate/live versions of these solutions as well as Chris' response.

Answer №3

For those considering using jQuery, the following code seems to be effective in Firefox: http://jsfiddle.net/Ek43k/89/

HTML

<a href="#" id="foo" class="inactive" >Drag me</a>

CSS

.inactive:active{color:red;}
.active:active{color:blue;}

jQuery

$('body').on('mousedown', 'a.inactive', function() {
    $(this).on('mousemove', function() {
        $(this).removeClass().addClass('active');
    });
});

$('body').on('mousedown', 'a.active', function() {
    $(this).removeClass().addClass('inactive');
});

Answer №4

To achieve the desired effect, simply apply the following CSS code:

#foo:hover {
    color: green;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Rearrange HTML list items automatically according to changes in numeric sort order

I am working on a web page that features a dynamic ranked list. The items in the list are assigned a specific rank order number which changes based on user interactions elsewhere on the page. I have been exploring different options to automatically reorgan ...

Could the problem with inset box-shadow and large border-radius on one side be related to Chrome?

Have you noticed a discrepancy in the inset box-shadow behavior with large border-radius on one side, particularly in Chrome? I'm curious about which browser is showing accurate results. Here's how it appears in Chrome: https://i.stack.imgur. ...

Gain access to PowerBI reports effortlessly without the need to input any credentials

Seeking guidance on calling Power BI reports from an ASP.NET C# web application while passing credentials, specifically without utilizing Azure AD. Access has been granted to certain users in the Power BI Service workspace with view permissions. We aim t ...

Using AJAX and PHP to dynamically fill HTML drop-down menus

In order to populate the DropDown controls on my HTML Form dynamically, I have implemented a code that utilizes AJAX to make a call to a .php file. This .php file is responsible for filling the DropDown control with values from a single column. Throughout ...

Typescript: Ways to fix the error 'rxjs/Rx does not have any exported member 'SubscriptionLike'

I'm attempting to replicate the steps outlined in this tutorial found here https://www.youtube.com/watch?v=gxCu5TEmxXE. However, upon running tsc -p, I encounter an error. Is there a specific import that I am missing? ERROR: node_modules/@angular/co ...

Adjust the size of an image within a canvas while maintaining its resolution

My current project involves using a canvas to resize images client-side before uploading to the server. maxWidth = 500; maxHeight = 500; //handle resizing if (image.width >= image.height) { var ratio = 1 / (image.width / maxWidth); } else { var ...

Selenium - Activating a flash button

Currently, I am facing an issue while trying to load a URL using Selenium on Mozilla browser. The webpage contains a 'Login' button created in flash that I need to click on. I have explored the following resources: 1.How to click an element in Se ...

wrap <td> data in a link with vue depending on certain conditions

I'm trying to customize the display of a particular table cell td. I want to show the data in a link if a certain condition is met, and if not, just show the data as text. However, I'm encountering some difficulties in implementing this. I have ...

Steps to prevent uib-timepicker from automatically adjusting time based on the Browser Timezone

Currently in my database, timestamps are stored in UTC format. On the frontend, I am implementing uib-timepicker for time editing and updating purposes. However, I do not want uib-timepicker to automatically convert the time from the server's timezone ...

The state change in React-Redux does not trigger a re-render

I successfully developed a large react-redux application with an undo feature in one component. While the state updates properly and re-renders the component along with its children, I noticed that the component's position on the page remains unchange ...

CSS: dealing with content that spills outside of a div

Currently, I am struggling to identify the solution to a problem on my website but I am unsure of how to categorize it. If you would like to take a look, here is the link: The issue at hand involves having a webpage divided into 3 standard sections: top, ...

Angular 4: Utilizing reactive forms for dynamic addition and removal of elements in a string array

I am looking for a way to modify a reactive form so that it can add and delete fields to a string array dynamically. Currently, I am using a FormArray but it adds the new items as objects rather than just simple strings in the array. Here is an example of ...

Is it possible to assign default values to optional properties in JavaScript?

Here is an example to consider: interface Parameters { label: string; quantity?: number; } const defaultSettings = { label: 'Example', quantity: 10, }; function setup({ label, quantity }: Parameters = { ...defaultSettings }) { ...

What is the process of retrieving the return value after creating data in Firestore

I have been experimenting with creating data using firestore in the following manner: createData({state}) { return db.collection('items').add({ title: state.title, ingredients: state.ingredients, creat ...

Is there a way to dynamically set the active panel of a JQuery Accordion when making a call?

Currently, I am faced with a scenario where I need to implement a greybox popup window using jQuery Accordion from the main page via links. I am curious to know if it is doable to specify a default active panel for the accordion when calling it. Below is ...

Is it possible to convert an object and/or a nested array with objects into a JSON string without relying on JSON.stringify?

Struggling to generate a correct JSON string from an object without relying on JSON.stringify(). Presenting my current implementation below - var my_json_encode = function(input) { if(typeof(input) === "string"){ return '"'+input+&apo ...

Unraveling nested JSON structures with varying formats in Javascript or Jquery: Step-by-step guide

var cart = [ { "Items": "", "category": "", "contents": [ { "Apple iPhone": "222", "French": "Bounjour", "id": 1234, "icon": "/images/bg.jpg", "callback": "use()", "pricetag":"false" } ] }, { "Items": "No 2" ...

Pressing the "Enter" key in a .Net WinForm Browser Control

How can I simulate the Enter key press event on a web page using the GeckoFX Web Control? I am unable to use SendKeys.Send({ENTER}) Is there a method to trigger the Enter key using JavaScript within a webpage? ...

What could be causing the issue with retrieving HTTP requests in Nest.js even after configuring the controller?

After the individual who departed from the company utilized Nest.js to create this server-side system. They established the auth.controller, auth.service, auth.module, auth-token, jwt.strategy, and jwt-payload, with everything properly configured. I verifi ...

React Router will not remount the component when using this.context.router.push

We have implemented a click handler that utilizes react router 2.0 to update the URL with this.context.router.push(). Here is the code snippet: selectRelatedJob(slug) { JobActionCreators.fetchJobPage(slug); JobsActionCreators.getRelatedJobs({'sl& ...