Have a page containing links.
When a link is clicked I want Javascript (or other) to check if the link contains (e.g. cheese)
If if does, then a modal should launch displaying the link.
example:
http://mylink/just-normal/ -- when this clicked, should proceed as normal
http://mylink/with-cheese/ -- when this clicked, should launch modal
http://mylink/another-link/ -- when this clicked, should proceed as normal
http://mylink/other-link/ -- when this clicked, should proceed as normal
Modal should display the full link.
Any assistance is appreciated.
Below is what I've got so far.
My specific question is:
Question: When I click any link on the site, a modal opens. It seems to be targeting all links and not just the links containing the specific word(s).
jQuery(function () {
jQuery(document).on('click', jQuery('a') , function(event){
var e = event;
event.preventDefault;
var that = event.target;
if(jQuery(that).is("span")){
that = jQuery(event.target).parent();
}
if(jQuery(that).attr('href')){
var url = jQuery(that).attr('href').toLowerCase();
if(jQuery.browser.webkit || jQuery.browser.mozilla && (url.indexOf('.my.test.here/') >=0)) {
ie_pointer(e, that);
}
else if (jQuery.browser.webkit && || jQuery.browser.mozilla (url.indexOf('something.else/') >=0)){
var overall = jQuery('.overall');
ie_pointer(e, overall, that);
}
}
});
});
function ie_pointer(event, obj, that){
event.preventDefault();
if(that){
var url = jQuery(that).attr('href');
}
else{
var url = jQuery(obj).attr('href');
}
jQuery('<div class="modal-backdrop"></div>').hide().appendTo(document.body).fadeIn();
jQuery(obj).after('<div class="modal-content" style="padding:10px"><h3 style="color:#333">Please copy the blue link below into Internet Explorer</h3><p style="font-size: 1.2rem; color:#333">This form is currently unavailable in Firefox & Chrome.</p><h4 style="color: #0099cc; max-width: 400px; word-wrap:break-word;">'+url+'</h4><i onclick="close_modal()" class="icon-remove"></i></button></div>');
}
function close_modal(){
jQuery(".modal-backdrop").fadeOut(function(){jQuery(this).remove()});
jQuery('.modal-content').fadeOut(function(){jQuery(this).remove()});
}
Your click event handler is set up for event delegation so that it only responds when event.target is an <a>:
jQuery(document).on('click', jQuery('a') , function(event){
Yet, inside of the handler, you have this:
if(jQuery(that).is("span")){
that = jQuery(event.target).parent();
}
Since you have that set to event.target, this if condition will never be true, so I'm not sure what you are trying to accomplish with it.
The remainder of the function runs when the <a> element has an href, but there too, you have if conditions that don't quite make sense:
if(jQuery.browser.webkit ||
jQuery.browser.mozilla && (url.indexOf('.my.test.here/') >=0)) {
ie_pointer(e, that);
} else if (jQuery.browser.webkit && ||
jQuery.browser.mozilla (url.indexOf('something.else/') >=0)){
var overall = jQuery('.overall');
ie_pointer(e, overall, that);
}
Your first condition will be true if the browser is webkit or if it is mozilla and the attribute contains your test string. Why don't you want to test for the string when the browser is webkit?
Your else if condition does the same thing, but you have a syntax error in it because you forget && here:
jQuery.browser.mozilla (url.indexOf('something.else/') >=0))
And, perhaps more importantly, why do you care what browser it is? JQuery deprecated the browser flags in version 1.9 because they are based on the navigator.userAgent, which has always been an unreliable way of browser sniffing.
Here's a slimmed down example of getting links that contain a certain string in their href to do one thing and all others to do something else using the standard CSS attribute selector:
var url = "console";
// Simply use the attribute wildcard selector to make sure
// you are only selecting links you care about in the first place
$("a[href*='" + url + "']").on("click", function(evt){
evt.preventDefault();
alert("You clicked a link that I care about!");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I should cause an alert().<br>
I should cause an alert().<br>
I should NOT cause an alert().<br>
I should NOT cause an alert().
Related
I'm using scrollmagic.io and am making an anchor navigation menu. I'm following this tutorial. The scroll works! Except it was scrolling back to the beginning and not to the page it should be at.
Here is my code:
// init controller
var controller = new ScrollMagic.Controller();
// animate scroll instead of a jump
controller.scrollTo(function(target) {
console.log('scroooooll');
console.log('target = '+target); // THIS IS PRINTING 0
console.log(typeof(target));
/* Commenting out what it should do for simplicity. */
});
// scroll action when you click the nav links
$(document).on('click', 'a[href^=#]', function(e) {
var id = $(this).attr('href'); // get the href of clicked link
if ($(id).length > 0) { // not empty links
e.preventDefault(); // prevent normal link action
// this is the function call
console.log('click');
console.log('id = '+id); // IT PRINTS CORRECT HERE
console.log(typeof(id));
controller.scrollTo(id); // scroll on click
// update the URL
if (window.history && window.history.pushState) {
history.pushState("", document.title, id);
}
}
});
And here is the output of my console log:
click
id = #{the-href-value}
string
scroooooll
target = 0
number
My Javascript is pretty rusty, but this doesn't seem right to me. Why is it changing my variable from a string to a 0 when I pass it as a parameter?
From the documents:
"This function will be used for future scroll position modifications.
This provides a way for you to change the behaviour of scrolling and
adding new behaviour like animation. The function receives the new
scroll position as a parameter and a reference to the container
element using this. It may also optionally receive an optional
additional parameter (see below)"
So, the first parameter is passed by controller.
You will get your parameter after that.
http://scrollmagic.io/docs/ScrollMagic.Controller.html#scrollTo
Try printing console.log(args);
controller.scrollTo(function(scrollPos, targetHrefISent) {
console.log('scroooooll');
console.log('target = '+targetHrefISent); // THIS IS PRINTING 0
console.log(typeof(targetHrefISent));
/* Commenting out what it should do for simplicity. */
});
I'm creating button which allows to enter post section. I'm checking if the body has class 'logged-in'. If test is false I want to create div container for message " You have to logi in" and append it to my section. My problem: Everytime when I click this button, new node is appended.
- How to invoke handler only once ?
if( !isOnline ) {
e.preventDefault();
var divForLog = document.createElement('div'),
linkElement = document.createElement('a');
linkElement.setAttribute('href', 'http://domain/login');
linkElement.text = "log in"
divForLog.innerHTML = "You have to ";
divForLog.appendChild(linkElement);
document.getElementById('last_questions').appendChild(divForLog);
}
There are several potential solutions, but I'll only list a couple here.
"Global"
Create a variable var loginShown in the scope where the handler is created. Then, change the ! isOnline check to ! isOnline && ! loginShown in the if statement, and set loginShown = true once you've appended the div.
Fiddle the DOM
Depending on the other content of #last_questions you can simply test whether or not the login element has already been appended using:
if ( ! document.getElementById('last_questions').querySelector('div > a[href="http://domain/login"]' ) ) {
...
}
Failing that, you can do as #NewToJS mentioned in the comments and add an attribute to the parent (once the div has been appended) which you can test for, such as an ID or data- attribute.
Unbind the Event
Easier if you're using jQuery, as mentioned by #Pawel you can simply unbind the event once the div has been appended. Probably the cleanest solution, but also trickier to implement. It also depends what else the handler is doing.
Try to set an attribute id to your div (container in my example) and when the user click check if the element with id already exist in document, if not add it :
if( !isOnline && document.getElementById('container').length==0) {
e.preventDefault();
var divForLog = document.createElement('div'),
linkElement = document.createElement('a');
linkElement.setAttribute('href', 'http://domain/login');
linkElement.text = "log in"
divForLog.innerHTML = "You have to ";
divForLog.appendChild(linkElement);
divForLog.setAttribute('id', 'container'); //Add id attribute
document.getElementById('last_questions').appendChild(divForLog);
}
Hope this helps.
If you're using jQuery something you could do(from the documentation .one | jQuery).
$("#button" ).one( "click", function() {
var divForLog = document.createElement('div'),
linkElement = document.createElement('a');
linkElement.setAttribute('href', 'http://domain/login');
linkElement.text = "log in"
divForLog.innerHTML = "You have to ";
divForLog.appendChild(linkElement);
document.getElementById('last_questions').appendChild(divForLog);
});
However another way I could think of would be to use jQuery's
$('#last_questions').html(divForLog);
Update
If thats not an option(most likely, as the #last_questions div may contain other stuff), you can create a <div id="log-in-alert"></div> which will live inside the #last_questions and only replace the html in this
Hope I was able to help??
I try to write a script based on JavaScript for replacing the current selected anchor element with it's inner HTML.
You can also find a simple running example in JSFiddle. To run the example, click on the first link, and the click the button.
So, for example, if I have the following HTML:
<p>
Wawef awef <em>replace</em> <strong>me</strong>
falwkefi4hjtinyoh gf waf eerngl nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg
<a href="http://www.anothersite.com/>replace me</a> klserng sreig klrewr
</p>
and I like when I click on some of the two anchors to remove the anchor with it's inner HTML. This mean, that if I click on the first anchor element, and click the appropriate button to replace the anchor the result should be like that:
<p>
Wawef awef <em>replace</em> <strong>me</strong> falwkefi4hjtinyoh gf waf eerngl
nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg <a href="http://www.anothersite.com/>replace me</a>
klserng sreig klrewr
</p>
My JavaScript code for this functionality is the following:
// Start tracking the click event on the document
document.addEventListener(
'click',
function(event)
{
// If right click, return
if(event.button == 2)
{
return;
}
// Get the current clicked document element
var link = event.target;
while(link && !(link instanceof HTMLAnchorElement))
{
link = link.parentNode;
}
// Get the element with ID wpf-remove-element-now
var clickedLink = document.getElementById("wpf-remove-element-now");
// If the element exists
if(clickedLink !== null)
{
// By executing this code, I am ensuring that I have only
// one anchor element in my document with this ID
// Remove the id attribute
clickedLink.removeAttribute('id');
}
// If ther is no link element
if(!link)
{
// Disable my "unlink" button
editor.commands.customunlinkcmd.disable();
// and return
return;
}
event.preventDefault();
event.stopPropagation();
// If the user has clickde on an anchor element then
// enable my "unlink" button in order to allow him to
// to replace the link if he like to.
editor.commands.customunlinkcmd.enable();
// Set the id attribute of the current selected anchor
// element to wpf-remove-element-now
link.setAttribute('id', 'wpf-remove-element-now');
}
);
var $unlink_button = document.getElementById('unlink');
$unlink_button.addEventListener(
'click',
function(event)
{
// Get the element with ID wpf-remove-element-now
var link = document.getElementById("wpf-remove-element-now");
// Create a new text node that contains the link inner HTML
var text = document.createTextNode(link.innerHTML);
// Make the replacement
link.parentNode.replaceChild(text, link);
}
);
Everything until now is correct, appart of the replacement of the link. I have try the above code, but the result I get is like the following one:
Wawef awef <em>replace</em> <strong>me</strong> falwkefi4hjtinyoh gf waf eerngl
nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg replace me klserng sreig klrewr
I mean the anchor is replaced with the text form of the inner HTML and not with the HTML form of the inner HTML.
So the question is, how can I do this kind of replacement.
You're creating a text node, so whatever you put in it will be interpreted as text. Instead, since you have the replacement tags predefined, you should create actual DOM elements to replace it with. Something like this could work: JSFiddle
var em_elem = document.createElement('em');
em_elem.appendChild(document.createTextNode("replace"));
var strong_elem = document.createElement('strong');
strong_elem.appendChild(document.createTextNode("me"));
var container_span = document.createElement('span');
container_span.appendChild(em_elem);
container_span.appendChild(strong_elem);
// Make the replacement
link.parentNode.replaceChild(container_span, link);
The answer was much simpler that I thought. I placed the solution below for anybody that need an equivalent solution :) :
$unlink_button.addEventListener(
'click',
function(event)
{
// Get the element with ID wpf-remove-element-now
var link = document.getElementById("wpf-remove-element-now");
// By this code you replace the link outeHTML (the link itself) with
// the link innerHTML (anything inside the link)
link.outerHTML = link.innerHTML;
}
);
Here you can find the running solution : JSFiddle
Note: The inspiration for this solution found in the web page.
I have a link, and if you drag this link then release, the link will keep his active state.
Example: http://jsfiddle.net/Ek43k/3/
<a href="javascript:void(0);" id="foo" >Drag me</a>
#foo:active{
color:red;
}
How can I prevent this?
(Only in IE and FF)
This is a known bug in Firefox, see https://bugzilla.mozilla.org/show_bug.cgi?id=193321
The bug has had an on-and-off status with several reports; the behavior is non-standard and browser-specific.
You can build a work-around for it, but you're stuck with javascript. After much searching, I determined that unless you're running in privileged mode (i.e. your code is in an extension), you cannot directly influence the pseudo-selector states. That means you're left with adding/removing a class name:
<a href="#" onmousedown="this.className = '';" ondragend="this.className = 'inactive';" id="foo" >Drag me</a>
Try it: http://jsfiddle.net/frsRS/
If you do have privileged mode, you can use the method that Firebug employs in their 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
Here is specific code for binding cross-browser delegates rather than putting the javascript inline (shown here for demonstration purposes, but generally bad practice)
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: http://jsfiddle.net/HYJCQ/
This uses the element's style rather than a css class, you can swap out the methods as desired.
Another way, as suggested by Supr, is to remove and immediately re-add the element from DOM. You can accomplish this using a delegate as well:
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
);
});
Try it: http://jsfiddle.net/ymPfH/
Both methods that utilize delegation are better approaches than looping elements -- that way, the script will apply to any a tags added to the page after load (similar to how jQuery's live or on methods work).
Documentation
Bugzilla entry - https://bugzilla.mozilla.org/show_bug.cgi?id=193321
Drag and Drop on MDN (ondragend) - https://developer.mozilla.org/en-US/docs/Drag_and_Drop
inIDOMUtils - https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/inIDOMUtils
Detach and reattach the link from the DOM tree to disable its active state. Do this when the drag ends and you've got this:
$('a').on('dragend',function(){
var $this = $(this),
$parent = $this.parent(),
$next = $(this.nextSibling); // $.next() doesn't include text
$this.detach().insertBefore($next);
});
No need to mess with your HTML or CSS or do away with :active. Seems to work in both FF and IE.
Edit: I don't usually write pure Javascript for DOM-handling so the quality of this might not be top notch, but here it is without jQuery:
(function(){
var previousOnload = window.onload || function noop(){};
window.onload = function (){
// Call any previously added onload callbacks
previousOnload();
// Add 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 so that it is put at the right position among the siblings
parent.insertBefore(this, position);
}
};
})();
I took care of a few issues that came to mind to make it fully plug-and-play. Tested in Opera, Chrome, Firefox and Internet Explorer.
Edit 2: Inspired by Chris, another way to apply the fix is to use the ondragend attribute directly to connect the deactivator (not tested):
<head>
<script>
function deactivate(){
var parent = this.parentNode,
position = this.nextSibling;
parent.removeChild(this);
// Using insertBefore instead of appendChild so that it is put at the right position among the siblings
parent.insertBefore(this, position);
}
</script>
</head>
<body>
Drag me
<body>
The downside is that it requires the ondragend attribute with javascript to be specified on each link manually/explicitly. I guess it's a matter of preference.
Final (?) Edit: See comments for delegate/live versions of these and Chris' answer.
If jQuery is an option, I think this code works, at least in FF: 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');
});
just add this CSS:
#foo:hover {
color: green;
}
finally i did this by following javascript..
function extractPageName(hrefString)
{
var arr = hrefString.split('/');
return (arr.length<2) ? hrefString : arr[arr.length-2].toLowerCase() + arr[arr.length-1].toLowerCase();
}
function setActiveMenu(arr, crtPage)
{
for (var i=0; i<arr.length; i++)
{
if(extractPageName(arr[i].href) == crtPage)
{
if (arr[i].parentNode.tagName != "DIV")
{
arr[i].className = "selected";
arr[i].parentNode.className = "selected";
}
}
}
}
function setPage()
{
hrefString = document.location.href ? document.location.href : document.location;
if (document.getElementById("but_a")!=null)
setActiveMenu(document.getElementById("but_a").getElementsByTagName("a"), extractPageName(hrefString));
}
if i click the ul without clicking the link.. its working.. when i click the link. it works until the page loads. after the page load, the ul back groud going default class not "selected" class..am new to tis.. am struggling so hard.. need help..??
I've added a jdFiddle with an example here:
http://jsfiddle.net/Suren/u4szQ/1/
$(document).ready(function() {
$("a.button").click(function () {
$(this).toggleClass("selected");
});
});
You've got too much javascript there.
After your posted fiddle. Here is a working fiddle.
Note you have a great deal of malformed HTML. You can't place divs in between list items. You can't have multiple objects on a page with the same ID (use a class instead).
After clicking on anchor the page is going to navigate to the url set on anchor's href attribute so whatever javascript operation you do is going to be lost after the page is loaded.
If you want to highlight the selected link the you can probably send the link id or some identifier along with the url and then check for it on page load and set the appropriate link selected.
By the way toggleClass adds or removes one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument.