I'm pretty new to Ember but this one seems very strange.
I've got a div on a template looking like so:
<div {{action "selectItem" item target="controllers.items"}}> Hello there! </div>
On my controller I have a simple action callback:
WebComponent.ItemController = Ember.ArrayController.extend(Ember.Evented, {
needs: ["settings"],
actions: {
selectItem: function (item) {
//This here won't fire unless I attach it to a <button> not a <div>
},
refreshList: function () {
//blah
},
...
}
},
...
} ...
In full disclosure, I am working inside Phonegap with the emulator.
Any ideas or even directions where to take this investigation?
I figured out the problem. It seems that Ember does not translates click events to touch events automatically (Ember 1.8) for tags like divs, spans, li, etc. It seems to do so for tags like button. So the solution for this is to add an attribute to map the event to the action. Use the on attribute with your action.
<div {{action "selectItem" item on="touchEnd" target="controllers.items"}}> Hello there! </div>
Some browsers/devices will not work properly with no-standard clickable DOM elements. Consider wrapping your <div /> with a link tag <a> and add the click event to the A element.
<a {{action "selectItem" item target="controllers.items"}}><div></div></a>
Second option (which worked for me for Safari on iPad is to just set the cursor to pointer.
<div style="cursor: pointer"></div>
This answer was on the comment of Vincent Gauthier https://github.com/emberjs/ember.js/pull/11373:
<button {{action 'process'}} {{action 'process' on="touchEnd"}}>Submut</button>
This was very helpful for me because when I try to put only on="touchEnd" it stopped working on desktop browser, so the multiple actions are the key
Related
I have a trash icon which user clicks on to delete current element from database. I want to make it work with ajax if user has javascript enabled. There are multiple items on page.
Don't know why but even after adding preventDefault, href works like regular href instead of performing ajax. It triggers ajax request without refreshing window only every second time I click on trash icon.
Do you know where is the problem?
$('.delete_bulletin').on('click', function (e) {
console.log('event');
e.preventDefault();
$.get($(this).attr('href')).done(
function () {
reloadBoardContent();
}
);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="bulletin_board">
<div class="bulletin_card">
<i>4. apríl 2018 14:50</i>
<h4>NAME</h4>
<p></p><p>htrhr</p><p></p>
<a class="delete_bulletin" href="/bulletin-board/delete/35/"><img style="max-height: 20px" src="/static/bulletin_board/icons/trash.png"></a>
</div>
<hr>
<div class="bulletin_card">
<i>4. apríl 2018 14:49</i>
<h4>NAME</h4>
<p></p><p>fdsafdfs</p><p></p>
<a class="delete_bulletin" href="/bulletin-board/delete/34/"><img style="max-height: 20px" src="/static/bulletin_board/icons/trash.png"></a>
</div>
<hr>
</div>
I'm pretty sure (but needs confirmation) that your reloadBoardContent() is updating the div where this <a> is located.
If that's the case, the anchor will be replaced and the event won't trigger to the newly created ones.
The solution is to use delegate events, which will make it work for dynamically added elements.
Do this instead:
$('#bulletin_board').on('click', '.delete_bulletin', function (e) {
If you don't replace the <div id="bulletin_board" itself but only its contents, everything shall be fine from now on.
On an xpage I have an editbox control and xe:namepicker nicely grouped beside each other with a Bootstrap add-on component.
However I would like to trigger the xe:namepicker when the cursor enters the editbox.
In the DOM I see that for the namepicker an anchor link is generated such as:
a class="glyphicon glyphicon-user xspPickerLink" href="javascript:;"
And I could trigger the click event via csjs
$("a.xspPickerLink").trigger('click');
But I happen to have multiple xe:namepicker-s on my xpage.
Does anyone have a clue how I can trigger a SPECIFIC xe:namepicker ?
You can work with wrapper elements:
<div id="namePicker1Wrapper">
<xe:namePicker id="namePicker1" pickerText="Select..."></xe:namePicker>
</div>
<div id="namePicker2Wrapper">
<xe:namePicker id="namePicker2" pickerText="Select..."></xe:namePicker>
</div>
Now you have the opportunity to select a SPECIFIC xe:namepicker:
$("#namePicker1Wrapper a.xspPickerLink").trigger('click');
I'm running into an issue with some Knockout code firing off a CSS3 animation. It works with one block of code, and doesn't on another. The idea is to show an animation when you add an item to the cart. The object in the code not working is coming up empty, where as the one working displays the product notification' div. The other issue is that $('#cart-nav a.first').click(); is not getting dispatched when this action is performed. This is not working in either scenario.
Below is where the code works (for the animation), and another where it does not. Appreciate any help. Thanks
Working code where CSS3 Animation fires off when you add an item to the cart. The class 'rise' triggers the animation. One working block of code, the other not working, and the JS below that. Thank you
Works
<div class="thumbnail product-image medium">
<div class="actions">
<div class="product-notification-cont">
<div class="product-notification"> Added to cart!</div>
</div>
Add to Cart
More Info
</div>
<a href="" data-bind="attr:{href:'/#products/'+$data.id}">
<img src="" data-bind="attr:{alt:$data.name, src:$root.servicePath+'products/'+$data.id+'/images/preview_image/medium?auth='+ax.JRR}" />
</a>
</div>
Doesn't work
<div class="product-info" data-bind="visible:!(productLoading())">
<h2 data-bind="text:product().name"></h2>
<div class="product-description" data-bind="html:product().description">
</div>
<div class="product-notification-cont">
<div class="product-notification"> Added to cart! </div>
</div>
<button class="button" data-bind="click:addProductToCart.bind($data,productMoreInfo())">Add to Cart</button>
<? } else { ?>
<h3><?=l(23)?></h3>
<? } ?>
</div>
JS (console.log in there for debugging purposes)
self.addProductToCart = function(data, event) {
var $productNotification = $(event.target).prev().children('.product-notification');
console.log($productNotification);
ax.Cart.addCartItem({product_id:data.id, name:data.name, description:data.description});
$('#cart-nav a.first').click();
$productNotification.addClass('rise');
$productNotification.on('animationend',function() {
$(this).removeClass('rise');
});
};
The main difference I spot is this:
The working data-bind binds $data as this:
data-bind="click:$root.addProductToCart.bind($data)"
The not-working data-bind binds $data and the first argument of addProductToCart:
data-bind="click:addProductToCart.bind($data,productMoreInfo())"
Knockout's default click handler signature is:
function(data, event) { }
which matches your addProductToCart signature. The second (faulty) data-bind creates these parameters:
productMoreInfo(), $data, clickEvent
I.e.: it adds the additional parameters in bind to the front of the arguments list.
The quick solution would be to create a new event listener that handles the extra parameters. However, I'd strongly suggest changing your approach altogether. You should look in to afterRender, the css binding and custom bindings. Avoid DOM related jQuery code in your view models.
seems a little trivial but am having a hard time solving it, i have a jquery function to select the class of a tag on click but the problem is that it selects every other tag underneath the tag clicked as well in structural order where as i only want the very first one
for example if i have
<div class="1">
<div class="2">
<div class="3">
<p class="4">Hello World</p>
</div>
</div>
</div>
and i clicked on the (p) tag that says hello world i would get an alert
saying 4 then 3 then 2 then 1
but like i said i only want the first one witch in this case is 4
here is my jquery code
$("*").dblclick(function(){
if(!$(this).hasClass("") && !$(this).hasClass("main")){
alert($(this).attr('class'));
}
});
i know the problem is happening because technically i am clicking all of the tags so it continus to loop trough but i still need a way to break it after the first class is selected or better yet is there a way to select only the topmost object
Just add return to the function like so:
$("*").dblclick(function(){
if(!$(this).hasClass("") && !$(this).hasClass("main")){
alert($(this).attr('class'));
return false;
}
});
I would pass in event to your click function, and after you've finished your logic, use event.stopPropagation(). This prevents the event from bubbling up to parent elements
$("*").dblclick(function(event){
if(!$(this).hasClass("") && !$(this).hasClass("main")){
alert($(this).attr('class'));
}
event.stopPropagation();
});
Run this example and look your console.
$("body > div").dblclick(function(){
console.log($(this).attr('class'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="1">
<div class="2">
<div class="3">
<p class="4">Hello World</p>
</div>
</div>
</div>
You should read about event bubbling and event propagation.
Here is function which does what you want:
$("*").dblclick(function(e){
if(!$(this).hasClass("") && !$(this).hasClass("main")){
alert($(this).attr('class'));
e.stopPropagation();
}
});
And here is working example:
https://jsfiddle.net/18sawk57/
Although it's not a good solution to attach event listening to all of the tags on the page. Much better solution is to add for example id or clickable class attribute for elements that should have event listening.
Here is another working example with better approach: https://jsfiddle.net/tr7aqask/
Here is another working example with bubbling disabled using jquery: https://jsfiddle.net/yc0481sm/
Using a jQuery Mobile button like:
<ul data-role="listview">
<li><a data-role="button" href="#" id="test">Test</a></li>
</ul>
I am attaching a tap handler like this:
$('#test').on('tap', function(event) {
event.preventDefault();
window.console.log('do something useful here');
});
The problem is that either preventDefault is blocking the JQM css changes to buttons like ui-btn-down/active/up/etc. or just adding the tap handler at all is preventing them. So it doesn't quite feel right to the user cause there is no visual impact of clicking the button.
Is there anyway around this problem? Perhaps manually assigning the classes in each handler - though that seems heavy handed.
Instead of preventing default actions of a link, you can use the button element:
<div role="main" class="ui-content">
<button id="test">Test</button>
<br /><br />
<input type="text" value="" id="output" />
</div>
$('#test').on('tap', function(event) {
$("#output").val(new Date());
});
jQM styles the button the same way, so there is no real difference.
Working DEMO
Upon further testing, my premise for this question was wrong. The issue appears to be the duration of the tap itself. If you tap too quickly the classes don't get applied, but a few ms longer and they do. I am closing this question.