Meteor 'click' event, wait for subscriptions during event - events

Is there a way for a click event to wait for subscriptions to be ready before moving on to next line within that event?
I have a nested selector for choosing nested categories. When I click the category I want to dive further into, I want the category list to slide left, then have the new category list to fade in once the subscription has become ready. Here is my code for the event so far:
'click .nested-selector-item': function (event, template) {
$('.nested-selector-page').toggle('slide', {direction: 'left'}, 250);
/* do some stuff to update subscription */
/* below needs to wait for subscription to change and be ready */
$('.nested-selector-page').toggle('fade', 250);
},
I do not want to load all categories because there are tens of thousands of them.
Is this possible within template events?

Related

Ajaxinate Endless scolling has stopped product Quick View from working

I am using Shopify "Streamline Theme" with quick product view and I recently added infinite scroll to products on each collection using Ajaxinate.js.
When I open a collection page it loads with some products which is supposed to do, The products already there work fine with quick view and quick add to cart and also.
The Infinite scroll works fine and it loads new product fine but the problem is raised when the new products loaded through AJAX call doesn't have work with the quick view function.
I have tried to create a callback function to activate the quick view with no success, using the theme initialisation code with no success.
function callBack(){
theme.init();
theme.initQuickShop();
};
document.addEventListener("DOMContentLoaded", function() {
var endlessClick = new Ajaxinate({
method: "scroll",
loadingText: 'Loading...',
callback: callBack
});
});
Edit -------
My problem, is that when the page is loaded only the initial loaded products quickview elements are loaded in the DOM. When the scroll more button is clicked, the newly loaded products are loaded without their respective quickview elements. Hence why the quickview does't work for them. The theme.js file comes with this initialisation code:
theme.reinitProductGridItem = function($scope) {
if (AOS) {
AOS.refreshHard();
}
if (theme.settings.currenciesEnabled) {
theme.currencySwitcher.ajaxrefresh();
}
// Reload quick shop buttons
theme.initQuickShop(true);
// Refresh reviews app
if (window.SPR) {
SPR.initDomEls();SPR.loadBadges();
}
// Re-register product templates in quick view modals.
// Will not double-register.
sections.register('product-template', theme.Product, $scope);
// Re-hook up collapsible box triggers
theme.collapsibles.init();
};
I have tried to integrate this into a callback but no success, the quickview modal doesn't seem to load for the newly loaded products:
function callBack(){
ReloadSmartWishlist();
var $container = $('#CollectionSection');
theme.reinitProductGridItem($container);
// I have tried the following init qith no success:
// theme.init();
// theme.initQuickShop(true);
// theme.initQuickShop();
// sections.register('product-template', theme.Product, $container);
// AOS.refreshHard();
};
document.addEventListener("DOMContentLoaded", function() {
var endlessClick = new Ajaxinate({
method: "click",
loadingText: 'Loading...',
offset: 0,
callback: callBack
});
});
I am missing something but what? :/
Note for other things like loading products images with the callback and the wishlist app, it works as intended...
When you load elements via AJAX and if the events are not attached to a parent element that is not removed from the DOM, those elements will not have an attached event to them.
The term used here is event delegation.
Here is an example of non-delegated event:
document.querySelectorAll('a').addEventListener('click', function(){
// Do something
})
Since you are attaching the event to the existing "a" elements if you add new 'a' via AJAX those elements will not have the event since Javascript already attached all the events and it will not reattach them if you don't specifically recall them again.
Here is an example of a delegated event:
document.querySelector('body').addEventListener('click', function(target){
let target = event.target;
if (target.tagName === 'A'){
// Do something here
}
})
Where we attach the event to the body tag ( where it's a better idea to attach it to a closer none-modified parent element of the ajax items ) and once we click we check if our target tag is an "a" and do something then.
So long story short, you will need to delegate the quick cart link so that it works after you load the items via AJAX.
Drip is correct you need to delegate your event, but for people like me it's hard to completely understand how to do that.
I'm not sure how your quickview is structured, but if you open it with a .click function and can use jquery use the [.on() function][1].
For example: I use a quickview that opens on a button click. My button is attached to my product-grid-item.liquid with this bit of code:
<div class="quick-view-button">
<a class="quick-view" data-handle="{{ product.handle }}" href="javascript:void(0);">Quick View</a>
</div>
My quickview function originally looked like this:
function quickView() {
$(".quick-view").click(function () {
//all of the quickview code
What happens is exactly like you described. The event listeners only loaded on the first product load but nothing after an AJAX load.
Using jquery's .on() binds the event listener to the element meaning when it's loaded in later it'll still have the event. Here's an example of what my code looks like after using .on()
function quickView() {
$('body').on('click','.quick-view',function(){
I really hope this helps you or someone else with this problem.
[1]: http://api.jquery.com/on/

Prevent the delete key from working on Kendo ListBox

I'm using Kendo on Razor pages using MVVM. On a particular page I have a pair of ListBoxes. I want to stop users from deleting items from the boxes with the delete key.
If I trap and prevent the remove event from working, that solves the problem, except you can't then use the toolbox or drag and drop to transfer items from one box to the other (edit: because move is a combination of change & remove events).
This is how I was stopping the remove event...
<select style="min-width: 600px" id="listboxImports" data-role="listbox"
data-text-field="title"
data-value-field="id"
data-selectable="multiple"
data-toolbar='{tools: ["transferTo", "transferFrom"]}'
data-connect-with="listboxSelected"
data-draggable="true"
data-template="template"
data-drop-sources="['listboxSelected']"
data-bind="source: imports, events: {remove: viewmodel.events.remove}"></select>
<script>
var viewmodel = new kendo.observable({
events: {
remove: function(e) {
e.preventDefault();
},
//
}
});
<script/>
I've also tried to trap the delete key's keydown event, but I cannot identify which of the many elements rendered when the ListBox is rendered is actually handling the event.
Can anyone tell me how I can have my cake and eat it please?
Took ma a while, inspired by the same question for kendo's Multiselect: https://docs.telerik.com/kendo-ui/controls/editors/multiselect/how-to/selection/prevent-removing-selected-items-on-backspace:
$("#listBoxA").parent().get(0).addEventListener('keydown', function(e) {
if (e.keyCode == kendo.keys.DELETE) {
e.stopImmediatePropagation();
e.preventDefault();
}
}, true)
Full dojo: https://dojo.telerik.com/aFaCIkez/3
The _keyDown handler is attached to the <ul> element. My solution attaches a new handler to its parent, using event capturing, so that handler will be executed before Kendo's, and thus stopping the event's propagation if the pressed key was delete.
Alternatively, a possible workaround is to set navigatable to false, but you obviously lose all keyboard functionality. Example: https://dojo.telerik.com/IHICAziR

Hide child grid when adding new main item

I have a grid that has child grid for each item, when i add a new item to the main grid, there is a stub for the child (with the toolbar etc and an empty grid for the child), I would like to hide the child grid when adding new one, i know i need the edit event, i just dont know how to get reference to the detailgrid for the item that the row was just created for input.
edit event has e.sender, e.container, e.model, first 2 reference the main grid of course as the event is raised by the main grid
The required behavior is not supported out of the box, however you can for example attach click event handler to the expanding arrows in the Grid. In the event handler you can prevent the expanding if current model is new. Please check the example below:
//Change Employees with your grid name
//the grid should have model ID defined
$("#Employees table").on("click", ".k-hierarchy-cell a", function (e) {
dataItem = $("#Employees").data("kendoGrid").dataItem($(e.srcElement).closest("tr"));
//check if is new record
if (dataItem.isNew()) {
e.preventDefault();
e.stopImmediatePropagation();
}
})
UPDATE (as requested): The above code should be executed in script tag (wrapped in document "ready" event handler) which is placed just after the Grid initialization code.

backbone.js click and blur events

I'm having some trouble with blur and click events in backbone. I have a view (code below) that creates a little search entry div with a button. I pop open this div and put focus on the entry field. If someone clicks off (blur) I notify a parent view to close this one. If they click on the button I'll initiate a search.
The blur behavior works fine, however when I click on the button I also get a blur event and can't get the click event. Have I got this structured right?
BTW, some other posts have suggested things like adding timers to the div in case its being closed before the click event fires. I can comment out the close completely and still only get the blur event. Do these only fire one at a time on some kind of first-com-first-served basis?
PB_SearchEntryView = Backbone.View.extend({
template: _.template("<div id='searchEntry' class='searchEntry'><input id='part'></input><button id='findit'>Search</button></div>"),
events: {
"click button": "find",
"blur #part": "close"
},
initialize: function(args) {
this.dad = args.dad;
},
render: function(){
$(this.el).html(this.template());
return this;
},
close: function(event){ this.dad.close(); },
find: function() {
alert("Find!");
}
});
I am not sure what the problem was, but here is the jsbin code.

Disable click event after touch and hold

I am developing an app iOS app in appcelerator and I got a table with user.
When I click on the user it opens the profile but I also want the user to be able to copy the name just by tap and hold for 2 seconds.
These two event works fine separately but right now after tap and hold the click event fires to. How can I prevent the click event from firing after tap hold?
// Set the timeout
var holdTime = 500, timeout;
// Create the table touch start event listener
table.addEventListener('touchstart', function(e) {
// Set the selected user id
var itemValue = e.row.value_full;
// Define the function
timeout = setTimeout(function(e) {
// Create the fade out animation
var fadeOut = Titanium.UI.createAnimation({
curve: Ti.UI.ANIMATION_CURVE_EASE_IN_OUT,
opacity: 0,
duration: 1000
});
// Create the loading screen
var copied = UI_messages.showFlash({label : 'Copied!'});
// Add the loading screen
win.add(copied);
// Save value to clipboard
Titanium.UI.Clipboard.setText(itemValue);
// Fade the message out
copied.animate(fadeOut);
}, holdTime);
});
// Create the event listener for touch move
table.addEventListener('touchmove', function() {
// Clear the timeout
clearTimeout(timeout);
});
// Create the event listener for touch move
table.addEventListener('touchend', function(e) {
// Clear the timeout
clearTimeout(timeout);
});
I've run into this problem before as well. The solution I used isn't very pretty, but it's the only effective way that I've found to suppress a touch event after a touch-and-hold.
The only working solution that I could find was to create a bool variable in a global namespace. In your setTimeout function, change the value of the bool to true to indicate that a touch-and-hold has occurred.
In the onClick event event for the row, check the global variable first to see if you've already created a touch-and-hold event - if you have, just return from the onClick event. This will effectively disable your click event when a touch-and-hold occurs.
Remember to set the global variable to false after the touch-and-hold function ends.

Resources