Simply counting each time a button is clicked - Ext JS - button

So I have the #add_button in my main app.js:
{ xtype: 'button', text: 'Add', itemId: 'add_criteria' }
I have the controller here that is listens for each click and attempts to add 1 each time the #add_button is clicked:
Ext.define('AM.controller.Add', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'#add_button': {
click: this.add
}
});
},
add: function(btn) {
var count = 0;
if (count <= 3)
{
count++;
console.log('Count is now ' + count;
}
else {
console.log('wut');
}
}
});
The controller is set up properly, however I can't seem to keep a count on the number of times clicked. It's telling me it's 'undefined'. Any ideas?
And yes I've seen the Sencha docs on the 'button' component. I, however am handling the event with a controller.

You are using count as a local variable, and initializing it to 0 every time your button is clicked. You need to make count a member variable of the controller.
Ext.define('AM.controller.Add', {
extend: 'Ext.app.Controller',
init: function() {
this.count = 0;
this.control({
'#add_button': {
click: this.add
}
});
},
add: function(btn) {
if (this.count <= 3)
{
this.count++;
console.log('Count is now ' + this.count);
}
else {
console.log('wut');
}
}
});

Related

Infinite scrolling with Meteor

I am trying to load 12 items only each time, until the user scroll all the way down and load another 12 elements
For some reason my code doesn't work. When i upload another item, i can see it in the admin panel so it is successfully uploaded but i can't see it in the normal user view. i can only view the first 12 items uploaded and it doesn't load anymore items when i scroll.
Here is my code in the client side
if (Meteor.isClient) {
var ITEMS_INCREMENT = 12; //this one refers to the number of elements to load
Session.setDefault('itemsLimit', ITEMS_INCREMENT);
Deps.autorun(function() {
Meteor.subscribe('items', Session.get('itemsLimit'));
});
Template.list_products.helpers({
applications: function () {
var limit = Session.get("itemsLimit");
//return Products.find({}, { sort: {createdAt: -1},limit: limit }); // render latest first
return Products.find({}, { sort: {createdAt: 1},limit: limit }); // render first first
}
});
Template.list_products.moreResults = function() {
// If, once the subscription is ready, we have less rows than we
// asked for, we've got all the rows in the collection.
return Products.find({}, { sort: {createdAt: -1},limit: limit });
}
// whenever #showMoreResults becomes visible, retrieve more results
function showMoreVisible() {
var threshold, target = $("#showMoreResults");
if (!target.length) return;
threshold = $(window).scrollTop() + $(window).height() - target.height();
if (target.offset().top < threshold) {
if (!target.data("visible")) {
// console.log("target became visible (inside viewable area)");
target.data("visible", true);
Session.set("itemsLimit",
Session.get("itemsLimit") + ITEMS_INCREMENT);
}
} else {
if (target.data("visible")) {
// console.log("target became invisible (below viewable arae)");
target.data("visible", false);
}
}
}
// The below line is to run the above func every time the user scrolls
$(window).scroll(showMoreVisible);
}
Here how i solved it:
if(Meteor.isClient) {
Session.set("itemsLimit", 9); // to set the limit to 9
lastScrollTop = 0;
$(window).scroll(function(event){
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) { // to detect scroll event
var scrollTop = $(this).scrollTop();
if(scrollTop > lastScrollTop){ // detect scroll down
Session.set("itemsLimit", Session.get("itemsLimit") + 9); // when it reaches the end, add another 9 elements
}
lastScrollTop = scrollTop;
}
});
}
It works like a charm now :)
You can implement it like this:
HTML File:
<template name="yourTemplateName">
<div id="divId">
{{#each dataArr}}
//your view here.
{{/each}}
</div>
{{#if noMoreItem}}
<span>No more items to show</span>
{{/if}}
</template>
JS File:
var pageNumber = new ReactiveVar(0);
var noMoreItem = new ReactiveVar(false);
var mainContainer = // Your element here example: document.getElementById('divId')
mainContainer.addEventListener('scroll', function(){
if(mainContainer.scrollHeight - mainContainer.scrollTop === mainContainer.clientHeight) {
getMoreItems();
}
});
var getMoreItems = function () {
if(pageNumber.get() < Math.floor(Counts.get('countItems')/12)) {
pageNumber.set(Number(pageNumber.get())+1);
Meteor.subscribe('pubName', pageNumber.get(), 12);
} else {
noMoreItem.set(true);
}
}
Template.yourTemplateName.rendered = function () {
pageNumber.set(0);
Meteor.subscribe('pubName', pageNumber.get(), 12);
}
Template.yourTemplateName.helpers({
'dataArr': function () {
return CollectionName.find();
},
'noMoreItem': function () {
return noMoreItem.get();
}
})
Publication:
Meteor.publish("pubName", function (pageNumber, pageSize) {
Counts.publish(this, 'countItems', Meteor.users.find(filter), {
noReady: true
});
return CollectionName.find({}, {
skip: pageNumber > 0 ? ((pageNumber) * pageSize) : 0,
limit: pageSize
})
});

moving a html element during swipe with chriswessels:hammer

This meteor client code uses chriswessels:hammer#4.0.2
, the swipeleft works by invoking console.log('moved left') but how can I get the html element to actually move with the finger? Thanks
Template.swipe.helpers({
'configureHammer': function() {
return function(hammer, templateInstance) {
let swipeleft = new Hammer.Swipe({
event: 'swipeleft',
pointers: 1,
velocity: 0.2
});
hammer.add(swipeleft);
return hammer;
}
},
'swipeGestures': {
'swipeleft .swipe': function(event, templateInstance) {
console.log('moved left');
}
}
});

Pinch event on iFrame Extjs 5

I want to detect pinch event on an IFrame (Extjs 5 Component).
What's wrong with this code??
Ext.create('Ext.ux.IFrame', {
autoScroll: true,
src: 'resources/docs/doc1.html',
cls: 'iframeStyle',
listeners: {
pinch: function (event) {
alert('event.scale= ' + event.scale);
}
}
})
Out of the box, Ext.ux.Iframe does not have "pinch" as an event. Only the events listed on the API can be added using the "listeners" syntax. http://docs.sencha.com/extjs/5.0/5.0.1-apidocs/#!/api/Ext.ux.IFrame
You'd want something along the lines of:
Ext.create('Ext.ux.IFrame', {
autoScroll: true,
src: 'resources/docs/doc1.html',
cls: 'iframeStyle',
listeners: {
afterrender: function(container) {
container.addManagedListener(container.el, "touchstart", function (event) {
alert('event.scale= ' + event.scale);
});
}
}
})
The code is untested but addManagedListener is what you'll want!

Meteor + Iron-Router - how do I update my template's data context in response to events the user generates in my template?

So I have a route that sets my template
Router.route('audit', {
path: '/audit/:audit_id/',
template: 'audit',
data: function() {
if (this.ready()) {
audit_obj = Audits.findOne({_id: this.params.audit_id});
lineitems = LineItems.find(JSON.parse(audit.query));
return {
audit_obj: audit_obj,
lineitems: lineitems
}
}
},
waitOn: function () {
return [
Meteor.subscribe('lineitems', this.params.audit_id),
Meteor.subscribe('audits')
]
}
}
Now, when my user takes certain actions on the page rendered by the audit template, I would like to update the audit object and also update the data context that the page is running with. Is this possible?
Something like:
Template.audit.events({
'click .something-button': function() {
// update the data context for the current audit template.
current_context.audit_obj.something = 'new something';
}
});
Yes:
Router.route('audit', {
path: '/audit/:audit_id/',
template: 'audit',
onRun: function() {
Session.set('audit', Audits.findOne(this.params.audit_id));
Session.set('lineitems', LineItems.find(JSON.parse(audit.query)).fetch());
}
data: function() {
if (this.ready()) {
return {
audit_obj: Session.get('audit'),
lineitems: Session.get('lineitems')
}
}
},
waitOn: function () {
return [
Meteor.subscribe('lineitems', this.params.audit_id),
Meteor.subscribe('audits')
]
}
}
and
Template.audit.events({
'click .something-button': function() {
// update the data context for the current audit template.
Session.set('audit', {..});
}
});
But you'll need to decide how to handle changes that come from the server, and may interfere with changes on the front end. So a better approach might be to leave the first part of the code (router) as is:
Router.route('audit', {
path: '/audit/:audit_id/',
template: 'audit',
data: function() {
if (this.ready()) {
return {
audit_obj: Audits.findOne(this.params.audit_id),
lineitems: LineItems.find(JSON.parse(audit.query))
}
}
},
waitOn: function () {
return [
Meteor.subscribe('lineitems', this.params.audit_id),
Meteor.subscribe('audits')
]
}
}
and just change the front end to update the collection:
Template.audit.events({
'click .something-button': function() {
// update the data context for the current audit template.
Audits.update( this.data.audit_obj._id, {..} );
}
});
Of course, that will update the data on the server, too.

pass parameter to action property from view in sencha touch

I have a button inside a view and I have set a action property of it so that I can listen to its tap event in controller as follows
view code
{
xtype:'button',
text:'SKIP',
action:'skip'
}
controller code
onSkipContact:function(){
console.log('tap');
}
now what I want to pass the parameter to onSkipContact action something like as follows
{
xtype:'button',
text:'SKIP',
action:'skip(data.index)' //i want to pass the index of record to the controller
}
so that I can read in controller as follows
onSkipContact:function(index){
console.log('tap' + index );
}
panel containing cv
Ext.define('ca.view.ContactInfoPanel',{
extend:'Ext.Panel',
xtype:'contactinfopanel',
requires: [ 'ca.view.ContactInfo','ca.view.ContactVote'],
config:{
layout:'vbox',
defaults: {
margin: '10 10 10 10'
} ,
items:[{
xtype:'contactinfo'
},{
xtype:'contactvote', // its a CV
}]
},
initialize:function(){
this.callParent();
}
});
here is the contactvote i.e. cv
Ext.define("ca.view.ContactVote",{
extend:'Ext.Container',
xtype:'contactvote',
requires:['Ext.Button'],
config:{
bottom:0,
width: '100%',
defaults: {
margin: '10 20 0 0'
} ,
items:[{
xtype:'button',
text:'SKIP',
action:'skip',
id:'skipbtn'
}]
},
initialize:function(){
console.log(this.data);
this.callParent();
}
});
First, store the data you want to pass to the handler method in the button itself. For example:
{
xtype: 'button',
text: 'SKIP',
action: 'skip',
// Give it the name you want, just ensure it won't
// overlap a property defined by Ext.
dataIndex: data.index
}
Ext event listeners are always passed the event source (in your case the button) as their first argument. So in your handler, you can access your data this way:
onSkipContact: function(button) {
var index = button.index;
console.log('tap' + index);
}
Try this, Set the index in button configuration
{
xtype:'button',
text:'SKIP',
action:'skip',
index : data.index
}
In controller action
onSkipContact:function(button){
// You can get index config like this
console.log('tap' + button.index );
}
I assumed that your have something like following configuration in controller
refs: {
skipBtn : 'button[action=skip]'
},
control: {
skipBtn : {
tap: 'onSkipContact'
}
}
Update
Try
this.getCv().down('button[action=skip]').index = record.data.index;
instead of
this.getCV().setData(record.data)
your button code remain
{
xtype:'button',
text:'SKIP',
action:'skip'
}

Resources