Problems with contenteditable span inside hyperlink in Firefox - html

I've got a contenteditable span placed inside an <a> tag. I'd like to be able to edit the text inside the span so it is important to:
place the cursor on mouseclick somewhere inside the span
select part of the text inside the span using the mouse
Both does not work in Firefox as soon as there is a href attribute in the hyperlink (which is also needed in my case). There is no problem without this attribute and there are no problems in Chrome.
Please try my example on JSFiddle.
<ul>
<li>
<a href="#">
<span contenteditable="true">PlacingCursorOrTextSelectionInFirefoxImpossible</span>
</a>
</li>
<li>
<a>
<span contenteditable="true">noProblemsHereSoFar</span>
</a>
</li>
</ul>

What you can do to improve the click behaviour is to prevent its propagation like this:
<a href="#">
<span contenteditable="true" onclick="event.stopPropagation();">
PlacingCursorOrTextSelectionInFirefoxImpossible
</span>
</a>
Unfortunately, this only allows to put the cursor inside the span, but it is somewhy put to its beginning, not where one have clicked.
To enable selecting, you need to prevent the dragging behaviour, but it is to be changed for the a element:
<a href="#" draggable="false">
<span contenteditable="true" onclick="event.stopPropagation();">
PlacingCursorOrTextSelectionInFirefoxImpossible
</span>
</a>
But wow, draggable="false" actually fixed the "cursor to beginning" bug! Here's the working example (tested in FF 47): https://jsfiddle.net/8v1ebkfd/4/

This works for me:
prevent click-default inside contenteditables
and for firefox, remove and add href-attribute to prevent placing the cursor at the start of the contenteditable-element
http://jsfiddle.net/uy4q0zcm/1/
// if contenteditable inside a link
document.addEventListener('click', e=>{
if (e.button !== 0) return;
if (e.target.isContentEditable) {
e.preventDefault();
}
if (e.explicitOriginalTarget && e.explicitOriginalTarget.isContentEditable) { // keyboard click firefox
e.preventDefault();
}
});
// prevent (Firefox) placing cursor incorrectly
document.addEventListener('mousedown', e=>{
if (!e.target.isContentEditable) return;
var link = e.target.closest('a');
if (link) {
const href = link.getAttribute('href')
link.removeAttribute('href');
setTimeout(()=>link.setAttribute('href', href))
}
});

Related

Routerlink in a routerling - Angular

Is it possible to have a routerLink in a div that contains another div with a routerLink?
<div [routerLink]="xy">
<span [routerLink]="yx">clickable Link</span>
</div>
The problem is, that it first redirects you to the first routerLink in the div and then to the routerLink in the span, if you click the text in the span. It should only redirect to the span's link. I already tried to add to the span, but without success:
(click)="stop($event)"
stop(event: Event) {
event.stopPropagation();
}
You must have some content/width/height in order to make the div & span clickable
<div routerLink="/one">
one
<span routerLink="/two" (click)="stop($event)">two</span>
</div>
In the component.ts file
stop(e: Event) {
e.stopPropagation();
}

Changing the "current" class of an element only works if the element has no href

I'm trying to make a navigation bar that has some CSS code for the current tab and it only works for the elements that don't have a page to load.
This is my HTML code:
<ul class="nav-menu" id="nav-menu">
<li>
<a class="current" href="home">Home</a>
</li>
<li>
Cars
</li>
<li>
T&C
</li>
<li>
Prices
</li>
<li>
Services
</li>
<li>
Contact
</li>
</ul>
And this is my jQuery code:
$('ul li a').click( function(){
if ( $(this).hasClass('current') ) {
$(this).removeClass('current');
} else {
$('li a.current').removeClass('current');
$(this).addClass('current');
}
});
As I mentioned above, for the last elements that have href="#" it works just fine, but when I press one that has a link, it just doesn't work.
Any suggestion is appreciated :)
When you click the href="home" or href="cars" ones, the browser follows the link, loading a completely new page. When you click ones that just have an anchor (href="#"), that's navigation within the page, so the page isn't reloaded.
To highlight those navigation entries when the home or cars page loads, you'll need to run code on those new pages that finds and highlights them once the DOM is loaded.¹
For instance, on the home page:
$("ul li a[href=home]").addClass("current");
¹ If you're targeting even semi-modern environments, you can have top-level code in a <script src="..." defer> tag. In modern environments, you can use <script type="module"> instead. In old environments, just put the script tag at the end of the body, just prior to </body>.
It's not entirely clear what you meant, but I think you need to disable the default link click behavior with event.preventDefault().
Declare event as an argument in the click function. Like this:
$('ul li a').click( function(event){
...
And write event.preventDefault() at the very beginning of the function.
Here is the complete code:
$('ul li a').click( function(event){
event.preventDefault();
if ( $(this).hasClass('current') ) {
$(this).removeClass('current');
} else {
$('li a.current').removeClass('current');
$(this).addClass('current');
}
});

Best practice to change class on <li> and its child <a> upon click

I have a <li> element and I'm changing the css class of the <li> element upon click, using the ng-click (setting its controller highlighted holder variable) and ng-class (checking whether the <li> is highlighted in the controller and applying two types of classes for the true/false cases).
however I also need to change the class of the <a> which is a sub-element of the <li> based on the highlighting flag as I need a different text color.
do I create two ng-class tags for the <li> and the <a> inside of it and repeat the condition? or is there a better way?
I mean, it seems excessive to do this:
<li ng-click="navCtrl.setNav(1)" ng-class="{ 'nav_items_selected': navCtrl.isNavPage(1) , 'nav_items': !navCtrl.isNavPage(1) }"><a ng-class="{ 'nav_selected_a': navCtrl.isNavPage(1) , 'nav_a': !navCtrl.isNavPage(1) }" href="#">Dashboard</a></li>
You can use directive for changing the class of li and child a. I think its much better to use directive for handling DOM stuffs. it is also reusable for your future codes. documentation for directive: https://docs.angularjs.org/guide/directive
you can do something like this:
app.directive('changeClass', ['$location', function($location) {
return {
restrict: 'A',
link: function(scope, elem, attrs) {
elem.bind('click', function(event) {
var aChild = elem.children('a');
if(!elem.hasClass('active-li')){
elem.addClass('active-li');
aChild.addClass('active-link');
} else {
elem.removeClass('active-li');
aChild.removeClass('active-link');
}
});
}
}
}]);
html
<li change-class class="">
<a href="#" class="">
Dashboard
</a>
</li>
working demo here here
You can probably target your <a> in css without applying another class to it, since you've already done that to its <li> ancestor.
https://jsfiddle.net/tvbL877w/
Let's say you've got this css code:
.selected {
background-color: red;
}
.selected .some-child {
background-color: blue;
}
and your html is something like this:
<ul>
<li ng-class="{selected: myBoolean}">
Let's get some <a href="#" class="some-child" ng-click="myBoolean = !myBoolean" >CAKES!!!</a>
</li>
</ul>

No text selection in input box inside anchor in Firefox

If a text input tag is placed inside an anchor, then in Firefox (on Windows) it is not possible to manipulate text inside the text box — text cursor doesn't change its position, and it is not possible to select the text. In Chrome you can change cursor position, but not select the text.
In some cases we can set the parent to be something else than anchor, yet is there a way to avoid this behaviour in general?
Here's the HTML code:
<p>No text select in FF:</p>
<a href="#">
<input type="text" value="7777" />
</a>
<p>Working text select in FF:</p>
<span>
<input type="text" value="8888" />
</span>
And the fiddle.
You can remove the href attribute when the input element is focused. As long as there is no href attribute, you will be able to select text inside the input field (tested in safari, chrome and firefox).
<a href="http://www.google.de" id="link">
link
<input type="text" id="input">
</a>
(function () {
var link = document.getElementById('link');
var input = document.getElementById('input');
var saveHref = null;
input.addEventListener('focusin', function () {
savedHref = link.href;
link.removeAttribute('href');
});
input.addEventListener('focusout', function () {
link.href = savedHref;
savedHref = null;
});
})();
Working example:
http://codepen.io/jjd/pen/JYwLVr
its because of the implementation error in browser.
actualy when we clicking browser it will look for the type of object
in this way
1.is this a link
2.is this any other type( input area,image,
why it first checking for type "link"
because clickig is firstly implemented for opening links,
anf its main usage is for open links
it detect first it as a link then it will call the
. openlink(example) function

How to hover multiple elements with only one fixed link

I've create a link on number 1, which has it's own width and height, so it covers all A,B,D,E letters (all li's are linkable).
Sample image: http://i.imgur.com/anuoGnJ.jpg
What i cannot do is to put a background hover effect on A,B,D,E letters, because the link on number 1 covers with it's height and width all of them.
Is there a way i can achieve this? I must stay limited to use only one link.
Thanks a lot in advance.
My code is:
HTML:
<span class="one">1</span> <span class="two">2</span>
<ul>
<li>
<span class="letter">A</span> <span class="letter">B</span>
</li>
<li>
<span class="letter">D</span> <span class="letter">E</span>
</li>
</ul>
CSS:
.one {float:left;}
.one a {float:left;position:relative;width:100px;height:60px;display:block;}
.letter {float:left;color:#000;}
.letter:hover {background:#ff0000;}
Ok.That's it.
http://jsfiddle.net/HECKM/3/
jQuery will get the .ONE href attribute value and apply to LI inside UL.
$(document).ready(function(){
var url = $('.one a').attr('href');
$('ul.test li').click(function(){
window.location = url;
});
});
Just prepare for your use.
Cya.