I have a "show link" that when clicked displays a hidden < li > containing other links.
These links happen to display at the exact co-ordinates of the "show link".
When "show Link" is clicked, its event is fired, but then the link below also is triggered.
How to I stop the newly shown links from being clicked when I click "show link"?
Edit:
I am providing the code, but it may complicate the issue. The setTapClickAction is to avoid the double click behaviour that you get using .on("touchstart click")
Inline script:
...
let $m = $('<a href="#"/>').text('Show Link');
$.setTapClickAction($m, function (el, e) {
$('li.location').fadeIn( 1000);
$(el).text("Show All").attr("href","https://example.com")
});
$('<p id="more-locations"/>').html($m).insertAfter(list);
...
main.js:
// function to set the tap or click action on an element.
// suggested usage:
// $.setTapClickAction('.subscription_show_button', function(){
// $modalElement.modal('show');
// });
$.setTapClickAction = function (selector, actionFunction){
if (typeof actionFunction !== 'function' ){
console.log('No Action Function given. Function tapClickButton');
return false;
}
let $obj;
if (typeof selector === 'string'){
$obj = $(selector);
} else if (selector instanceof $) {
$obj = selector;
} else {
console.log('No element for action: ' + selector);
return false;
}
let touchmoved;
$obj.on('click',function(e){
actionFunction($(this), e);
console.log("click fired by " + this);
}).on('touchend',function (e) {
if (touchmoved !== true) {
actionFunction($(this), e);
}
}).on('touchstart', function () {
$(this).off('click');
touchmoved = false;
console.log("touchstart fired by " + this);
}).on('touchmove', function () {
touchmoved = true;
});
};
edit2:
Here is a link to the production site. https://t.starstarmobile.com/5/SESSIONIDB10/quick2?phone=8887186545 click or tap the "find other centers near you"
So my answer to the problem was to use .preventDefault() on any links that did not have an href value. I also added namespaces so that the events could be modified multiple times.
// function to set the tap or click action on an element.
// suggested usage:
// $.setTapClickAction('.subscription_show_button', function(){
// $subscriptionModal.modal('show');
// });
$.setTapClickAction = function (selector, actionFunction) {
let $obj, touchmoved, hasHref;
let namespace = "";
if (typeof actionFunction !== 'function') {
console.log('No Action Function given. Function tapClickButton');
return false;
}
if (typeof selector === 'string') {
$obj = $(selector);
//set the name space
namespace = selector.charAt(0) !== '.' ? '.' + selector : selector;
// console.log("string selector", selector);
} else if (selector instanceof $) {
$obj = selector;
// console.log("jquery Instance", selector);
} else {
console.log('No element for action:', selector);
return false;
}
//look for valid href or exec e.preventDefault
let href = $obj.attr("href");
if (href !== '#' && href !== undefined) {
hasHref = true;
// console.log ("Href: " + href)
}
//remove previously set events
$obj.off('click' + namespace);
$obj.off('touchstart' + namespace);
$obj.off('touchend' + namespace);
$obj.off('touchmove' + namespace);
//set events
// console.log('namespace: '+ namespace);
$obj.on('click' + namespace, function (e) {
if (!hasHref) {
e.preventDefault();
}
actionFunction($(this), e);
// console.log("click fired by ", this);
}).on('touchend' + namespace, function (e) {
if (touchmoved !== true) {
actionFunction($(this), e);
}
}).on('touchstart' + namespace, function (e) {
if (!hasHref) {
e.preventDefault();
}
$(this).off('click' + namespace);
touchmoved = false;
// console.log("touchstart fired by:", this, e.currentTarget.getAttribute("href"));
}).on('touchmove' + namespace, function () {
touchmoved = true;
});
};
Related
Hallo i am trying to show a custome view after draging document to my screen,my code is working without bugs but the problem i could not have any update until the page redirecting to other page cause after drag a file.
i am redirecting my page to other page if document draged and my code worked corectly in other module but i do not get why in this module it does not response until the page is redirecting .....
<div ngf-drop ngf-select ng-model="files" ngf-multiple="true" ngf-allow-dir="true" ng-if="dropIsVisible === true">
<div class="drop-area-full-page">
<div class="drop-area-full-page__graphic"></div>
<div class="drop-area-full-page__info" id="drop-area-full-page__info" ng-bind-html="dropText"></div>
</div>
</div>
$window.addEventListener("dragenter", function (e) {
if (isFile(e)) {
lastTarget = e.target;
$scope.dropIsVisible = true;
name = getName($scope, getParent());
$scope.dropText =
"<b> Dokument ablegen zu </b>" + "<b>" + name+ "</b>";
}
});
$window.addEventListener("dragleave", function (e) {
e.preventDefault();
if (e.target === document || e.target === lastTarget) {
$scope.dropIsVisible = false;
}
});
$window.addEventListener("dragover", function (e) {
e.preventDefault();
$scope.dropIsVisible = true;
});
function getParent() {
return {
entityName: $stateParams.entity,
id: $scope.parentId
};
}
$window.addEventListener("drop", function (e) {
e.preventDefault();
$scope.dropIsVisible = true;
var qs = e.dataTransfer.files[0].name;
var parent = getParent();
DokumentUploadMixin.Prepare(qs, e.dataTransfer.files[0], $scope, parent, projection, qs);
//$window.location.href = routeUtils.getCreateDokumentUrl("Dokument", getParent(), projection, qs);
});
};
function isFile(evt) {
var dt = evt.dataTransfer;
for (var i = 0; i < dt.types.length; i++) {
if (dt.types[i] === "Files") {
return true;
}
}
return false;
}
and as i wrote this code worked in other module but in this module it work just after the page start redirecting to other page....
any help to let ng-if respond ?
You added custom event listeners, which are not tracked by Angularjs. In order to make it work you have to cover everything inside addEventListener callback with $scope.$apply to tell angular update the model.
$window.addEventListener("dragenter", function (e) {
$scope.$apply(function() {
if (isFile(e)) {
lastTarget = e.target;
$scope.dropIsVisible = true;
name = getName($scope, getParent());
$scope.dropText =
"<b> Dokument ablegen zu </b>" + "<b>" + name+ "</b>";
}
});
});
$window.addEventListener("dragleave", function (e) {
$scope.$apply(function() {
e.preventDefault();
if (e.target === document || e.target === lastTarget) {
$scope.dropIsVisible = false;
}
});
});
$window.addEventListener("dragover", function (e) {
$scope.$apply(function() {
e.preventDefault();
$scope.dropIsVisible = true;
});
});
Here is a great article about angular internals and how it works.
Given the following snippet of code
var empowerInstance = null;
function onClick_btnSendMessage() {
var childIFrame = window.document.getElementById("editorFrame");
if (!empowerInstance) {
empowerInstance = EditorAPI.getInstance(childIFrame.contentWindow, window.location.origin);
}
empowerInstance.document.hasChanged(hasChangedCallback);
}
function hasChangedCallback(returnValue) {
console.log("empowerInstance.document.hasChanged = " + returnValue.isDirty);
if (returnValue.success === true && returnValue.isDirty === true) {
empowerInstance.document.save(saveCallback);
}
}
function saveCallback(returnValue) {
console.log("empowerInstance.document.save = " + returnValue.success);
if (returnValue.success === false) {
console.log(returnValue.message);
}
}
window.addEventListener("DOMContentLoaded", function (event) {
console.log("DOM fully loaded and parsed");
if (typeof location.origin === "undefined")
window.location.origin = window.location.protocol + "//" + window.location.host;
document.getElementById("btnSendMessage").addEventListener("click", onClick_btnSendMessage);
});
Instead of wiring the button up , I'd like to fire the code from the activation of a Bootstrap tab event.
$('a[data-toggle="tab"]').on("shown.bs.tab", function (e) {
onClick_btnSendMessage(); // Naive way, as this does not wait
var target = $(e.target).attr("data-EditorUrl"); // activated tab
var childIFrame = $("#editorFrame");
childIFrame.attr("src", target);
});
So my question is "How do I wait on this function to complete before changing the source of childIFrame?".
empowerInstance.document.hasChanged(hasChangedCallback);
I conceptually understand the use of Promises and Callbacks, but writing one that functions correctly is a different story.
UPDATED
This version is refactored to eliminate the button handler, thus improving readability.
The usage is also important. When the page loads for the first time it is positioned on a tab. This tab is associated to a document that is hosted in an iFrame. If the user edits this document then tries to change tabs, I'd like to invoke the check for being dirty/save, then once saved, move to the next tab/document. There is also the case that switching between tabs/documents won't cause a save because the document is not dirty.
var empowerInstance = null;
function hasChangedCallback(returnValue) {
console.log("empowerInstance.document.hasChanged = " + returnValue.isDirty);
if (returnValue.success === true && returnValue.isDirty === true) {
empowerInstance.document.save(saveCallback);
}
}
function saveCallback(returnValue) {
console.log("empowerInstance.document.save = " + returnValue.success);
if (returnValue.success === false) {
console.log(returnValue.message);
}
}
$(function () {
if (typeof location.origin === "undefined") {
window.location.origin = window.location.protocol + "//" + window.location.host;
}
$('a[data-toggle="tab"]').on("shown.bs.tab", function (e) {
var childIFrame = $("#editorFrame");
if (!empowerInstance) {
empowerInstance = EditorAPI.getInstance(childIFrame[0].contentWindow, window.location.origin);
}
empowerInstance.document.hasChanged(hasChangedCallback);// Need to wait for completion
var target = $(e.target).attr("data-EditorUrl"); // activated tab
childIFrame.attr("src", target);
});
});
Thank you,
Stephen
I've refactored your code to show how this can be done using promises.
function onClick_btnSendMessage() {
var childIFrame = window.document.getElementById("editorFrame");
if (!empowerInstance) {
empowerInstance = EditorAPI.getInstance(childIFrame.contentWindow, window.location.origin);
}
var doc = empowerInstance.document;
return hasChanged(doc).then(function() { return save(doc) })
}
function hasChanged(doc) {
return new Promise(function(resolve, reject) {
doc.hasChanged(function(returnValue) {
if (returnValue.success === true && returnValue.isDirty === true) {
resolve(returnValue)
} else {
reject(returnValue)
}
})
})
}
function save(doc) {
return new Promise(function(resolve, reject) {
doc.save(function(returnValue) {
if (returnValue.success === false) {
console.log(returnValue.message);
reject(returnValue)
} else {
resolve(returnValue)
}
})
})
}
// ------
$('a[data-toggle="tab"]').on("shown.bs.tab", function(e) {
onClick_btnSendMessage().then(function() {
var target = $(e.target).attr("data-EditorUrl"); // activated tab
var childIFrame = $("#editorFrame");
childIFrame.attr("src", target);
}).catch(function(error) {
// handle the error
console.error('Error!', error)
})
});
You can use some higher order functions to do what you want. Instead of passing the hasChangedCallback and saveCallback directly to the empowerInstance.document methods, you'll instead invoke a function that returns those callbacks, but also passes along your own callback that you'll call once all the async operations have finally completed. Here's what it'll look like:
$('a[data-toggle="tab"]').on("shown.bs.tab", function (e) {
var target = $(e.target).attr("data-EditorUrl"); // activated tab
onClick_btnSendMessage(function () {
var childIFrame = $("#editorFrame");
childIFrame.attr("src", target);
});
});
function onClick_btnSendMessage(myCallback) {
var childIFrame = window.document.getElementById("editorFrame");
if (!empowerInstance) {
empowerInstance = EditorAPI.getInstance(childIFrame.contentWindow, window.location.origin);
}
empowerInstance.document.hasChanged(getHasChangedCallback(myCallback));
}
function getHasChangedCallback(myCallback) {
return function hasChangedCallback(returnValue, myCallback) {
console.log("empowerInstance.document.hasChanged = " + returnValue.isDirty);
if (returnValue.success === true && returnValue.isDirty === true) {
empowerInstance.document.save(getSaveCallback(myCallback));
}
}
}
function getSaveCallback(myCallback) {
return function saveCallback(returnValue) {
console.log("empowerInstance.document.save = " + returnValue.success);
if (returnValue.success === false) {
console.log(returnValue.message);
}
myCallback && myCallback(); // make sure myCallback isn't null before invoking
}
}
It's not exactly attractive, but it should get you what you want.
I have been trying to trigger right click even when the users left click.
I have tried trigger, triggerHandler, mousedown but I wasn't able to get it to work.
I'm able to catch the click events themselves but not able to trigger the context menu.
Any ideas?
To trigger the mouse right click
function triggerRightClick(){
var evt = new MouseEvent("mousedown", {
view: window,
bubbles: true,
cancelable: true,
clientX: 20,
button: 2
});
some_div.dispatchEvent(evt);
}
To trigger the context menu
function triggerContextMenu(){
var evt = new MouseEvent("contextmenu", {
view: window
});
some_div.dispatchEvent(evt);
}
Here is the bin: http://jsbin.com/rimejisaxi
For better reference/explanation: https://stackoverflow.com/a/7914742/1957036
Use the following code for reversing mouse clicks.
$.extend($.ui.draggable.prototype, {
_mouseInit: function () {
var that = this;
if (!this.options.mouseButton) {
this.options.mouseButton = 1;
}
$.ui.mouse.prototype._mouseInit.apply(this, arguments);
if (this.options.mouseButton === 3) {
this.element.bind("contextmenu." + this.widgetName, function (event) {
if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
$.removeData(event.target, that.widgetName + ".preventClickEvent");
event.stopImmediatePropagation();
return false;
}
event.preventDefault();
return false;
});
}
this.started = false;
},
_mouseDown: function (event) {
// we may have missed mouseup (out of window)
(this._mouseStarted && this._mouseUp(event));
this._mouseDownEvent = event;
var that = this,
btnIsLeft = (event.which === this.options.mouseButton),
// event.target.nodeName works around a bug in IE 8 with
// disabled inputs (#7620)
elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
return true;
}
this.mouseDelayMet = !this.options.delay;
if (!this.mouseDelayMet) {
this._mouseDelayTimer = setTimeout(function () {
that.mouseDelayMet = true;
}, this.options.delay);
}
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted = (this._mouseStart(event) !== false);
if (!this._mouseStarted) {
event.preventDefault();
return true;
}
}
// Click event may never have fired (Gecko & Opera)
if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
$.removeData(event.target, this.widgetName + ".preventClickEvent");
}
// these delegates are required to keep context
this._mouseMoveDelegate = function (event) {
return that._mouseMove(event);
};
this._mouseUpDelegate = function (event) {
return that._mouseUp(event);
};
$(document)
.bind("mousemove." + this.widgetName, this._mouseMoveDelegate)
.bind("mouseup." + this.widgetName, this._mouseUpDelegate);
event.preventDefault();
mouseHandled = true;
return true;
}
});
Now at the function calling event use mouseButton : 3 for right click and 1 for left click
Let us consider this function:
function validateField(selector) {
$(selector).on("change, blur", function() {
// do stuff
});
}
That element could have an id=selector or a class=selector. How can I proceed with such abstraction?
You could simply refer to both by doing something like this:
function validateField(selector) {
var $selector = $('#'+selector+', .'+selector); // This will reference every class and id with the selector's name
$selector.on("change, blur", function() {
// do stuff
});
}
You might wanna try something like this, try to see if it's ID first, if it returns 0 as length, try class. But this isn't an good way to do it, maybe you can also try with a flag
function validateField(selector) {
var $selector = $('#' + selector);
if ($selector.length === 0) {
$selector = $('.' + selector)
}
$selector.on("change, blur", function() {
// do stuff
});
}
With an flag
function validateField(selector, classSelect) {
var $selector;
if (classSelect === true) {
$selector = $('.' + selector)
} else {
$selector = $('#' + selector)
}
$selector.on("change, blur", function() {
// do stuff
});
}
This function will accommodate both ID and class selectors:
function validateField(selector, Type) {
var SelectorString = "";
if (Type == "ID")
SelectorString = "#" + selector;
else if (Type == "Class")
SelectorString = "." + selector;
else
return; // invalid so don't create event handler.
$(SelectorString).on("change, blur", function() {
// do stuff
});
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
i am trying to trigger a url when click on a button, when click on the delete button it triggers the JS Alert but it is not passing the link, it removes the button instead. how can make it process the link once i confirm the alert?
js code
<script>
$(function() {
$('#demo').confirmOn('click', function() {
$(this).remove();
});
});
</script>
html
<a href="index.php?page=test:delete&item_id={item_id}" id="demo">
<input type="button" class="log_button" value="Delete"/>
ConfirmOn code..
(function($) {
var confirmOn = $.confirmOn = {};
confirmOn.providedOptions = {};
confirmOn.defaultSettings = {
questionText: 'Are you sure?',
classPrepend: 'confirmon',
textYes: 'Yes',
textNo: 'No'
};
confirmOn.overrideDefaultSettings = function(settings) {
confirmOn.defaultSettings = $.extend({}, confirmOn.defaultSettings, settings);
};
confirmOn.setOptions = function($element, options) {
options = $.extend({}, confirmOn.defaultSettings, options);
$element.data('confirmon', {
options: options
});
};
confirmOn.createOverlay = function($element) {
var classPrepend = $element.data('confirmon').options.classPrepend;
return $('<div/>').addClass(classPrepend + '-overlay').hide().appendTo('body');
};
confirmOn.showOverlay = function($element) {
var classPrepend = $element.data('confirmon').options.classPrepend;
$('.' + classPrepend + '-overlay').fadeIn();
};
confirmOn.deleteOverlay = function($element) {
var classPrepend = $element.data('confirmon').options.classPrepend;
$('.' + classPrepend + '-overlay').fadeOut(function(){
$(this).remove();
});
};
confirmOn.createBox = function($element) {
var classPrepend = $element.data('confirmon').options.classPrepend;
var questionText = $element.data('confirmon').options.questionText;
var textYes = $element.data('confirmon').options.textYes;
var textNo = $element.data('confirmon').options.textNo;
var $box = $('<div/>').addClass(classPrepend + '-box').hide().appendTo('body');
$('<p class="' + classPrepend + '-content"/>')
.html(questionText)
.appendTo($box);
$('<button class="' + classPrepend + '-button ' + classPrepend + '-button--yes"/>')
.html(textYes)
.appendTo($box);
$('<button class="' + classPrepend + '-button ' + classPrepend + '-button--no"/>')
.html(textNo)
.appendTo($box);
$('.' + classPrepend + '-button').on('keydown', function(e){
if (e.which === 9) { //Tab key
e.preventDefault();
$('.' + classPrepend + '-button').not(this).focus();
}
});
};
confirmOn.showBoxAndFocusNo = function($element) {
var classPrepend = $element.data('confirmon').options.classPrepend;
$('.' + classPrepend + '-box').fadeIn(function(){
$(this).children('button').eq(1).focus();
});
};
confirmOn.deleteBox = function($element) {
var classPrepend = $element.data('confirmon').options.classPrepend;
$('.' + classPrepend + '-box').fadeOut(function(){
$(this).remove();
});
};
$.confirmOn.handleEscKey = function($element) {
$(document).on('keydown.confirmon.close', function(e){
if (e.which === 27) { //Esc key
$.confirmOn.deleteOverlay($element);
$.confirmOn.deleteBox($element);
$(document).off('keydown.confirmon.close');
}
});
}
confirmOn.convertArguments = function(options, events, selector, data, handler) {
if (typeof options === 'object') {
$.each(options, function(key, val) {
if (typeof val === 'string') { //Options provided so shift all args to left
confirmOn.providedOptions = options;
options = events;
events = selector;
selector = data;
data = handler;
return false;
} else { //No options
confirmOn.providedOptions = {};
}
});
} else {
confirmOn.providedOptions = {};
}
if (selector == null && data == null && handler == null) {
//(events[S], handler)
selector = events;
events = options;
} else if (data == null && handler == null) {
//(events[S], selector, handler)
//(events[S], data, handler)
data = selector;
selector = events;
events = options;
} else {
handler = data;
data = selector;
selector = events;
events = options;
}
if (typeof events === 'object') {
//Implementation .on( events [, selector ] [, data ] )
return {
events: events,
selector: selector,
data: data
};
} else {
//Implementation .on( events [, selector ] [, data ], handler(eventObject) )
return {
events: events,
selector: selector,
data: data,
handler: handler
};
}
};
$.confirmOn.attachHandlers = function($element, handler, event) {
var classPrepend = $element.data('confirmon').options.classPrepend;
$('.' + classPrepend + '-box button').eq(0).on('click', function(){
$.confirmOn.deleteOverlay($element);
$.confirmOn.deleteBox($element);
handler.call($element.get(), event, true); //Call the handler function. the TRUE parameter indicates that the user pressed the YES button
});
$('.' + classPrepend + '-box button').eq(1).on('click', function(){
$.confirmOn.deleteOverlay($element);
$.confirmOn.deleteBox($element);
handler.call($element.get(), event, false); //Call the handler function. the FALSE parameter indicates that the user pressed the YES button
});
};
$.fn.confirmOn = function(options, events, selector, data, handler) {
var userHandler;
if (typeof events === 'function') {
userHandler = events;
events = confirmHandler;
} else if (typeof selector === 'function') {
userHandler = selector;
selector = confirmHandler;
} else if (typeof data === 'function') {
userHandler = data;
data = confirmHandler;
} else if (typeof handler === 'function') {
userHandler = handler;
handler = confirmHandler;
}
var $element = $(this);
var onArgs = $.confirmOn.convertArguments(options, events, selector, data, handler);
$.confirmOn.setOptions($element, $.confirmOn.providedOptions);
$element.on(onArgs.events, onArgs.selector, onArgs.data, onArgs.handler);
function confirmHandler(event) {
event.preventDefault();
$.confirmOn.createOverlay($element);
$.confirmOn.showOverlay($element);
$.confirmOn.createBox($element);
$.confirmOn.showBoxAndFocusNo($element);
$.confirmOn.handleEscKey($element);
$.confirmOn.attachHandlers($element, userHandler, event);
};
};
}(jQuery));
Use confirm():
Try this:
$("#demo").click(function() {
var confirm1 = confirm('Dialogue');
if (confirm1) {
$(this).remove();
return true;
} else {
return false;
}
});
UPDATE
$(function () {
$('#demo').confirmOn('click', function (e, confirmed) {
if (confirmed) { // Clicked yes
document.location.href= $(this).attr('href');
$(this).remove();
$('#msg_button_1').remove();
} else { // Clicked no
$('#msg_button_1').fadeIn();
}
});
});
JSFiddle Demo
Edited
<script>
$(function() {
$('.log_button').confirmOn('click', function(e, confirmed) {
if(confirmed){
//$('#demo').remove();
$('#demo').click();
}else{
alert("not go");
}
});
});
</script>
is this the thing that you actually want to do? click the button and then go to the link?