Detect clicks on button array with a single method - arrays

Im working in a school project, a minesweeper. Will be 20x20, so it has 400 buttons. Its there a way to add an actionEvent/actionPerformed and implement a generalized method for the whole array? Or there is an easier way?

Maybe something like that (using jQuery for convenience but you can do it with Vanilla JS too):
Your HTML:
<div id="buttonsHolder">
<button data-num=1>1</button>
<button data-num=2>2</button>
<button data-num=3>3</button>
...
<button data-num=4>4</button>
</div>
Your JavaScript:
$('#buttonsHolder').on('click', 'button', (function(evt){
var buttonNum = $(this).attr('data-num');
// Now, buttonNum variable holds the button number has clicked.
});
Of course instead of use data-num atribute you can use whatever data you need.

You are placing the buttons inside a container (i suppose). Add a actionhandler to that to capture a click. And read the 'target' variable of the event, and see if that is a button

Related

Tag Manager Variable from a parent of click element (toggle)

Here is the structure of the toggle:
<div data-id="thisIsTheID" class="abc">
<div class="edf">
<button value="false"></button>
</div>
</div>
The trigger only works with click >> all elements >> click classes contains edf. I tried click element matches css selector
div.abc
div.abc *
div.abc button
but none will work as trigger.
However, I want the data-id as variable in Google Tag Manager in order to differentiate between different toggles.
How do I create a trigger that works and how do I get the variable?
Here the actual code and debugger view:
Try making a custom JS variable like so:
function(){
return {{Click Element}}.parentElement.getAttribute("data-test-id");
}
It should return the value of your attribute on click.
But the classes look auto-generated. They feel like they can and will change on cache refresh or on front-end builds. I would try to use selectors like div[data-test-id] * or even div[data-test-id=isAgePolicy] *

angularJs disabling form buttons on submit

in my Angular 1.x app I am getting a list of Offers via an api call to my backend.
For each Offer returned in the reply I am creating an ng-form. I then display the forms in a modal and I want to be able to disable each form's submit button when it has been clicked to avoid multiple clicks whilst the form data is posted to the back end.
This seems tricky since the number of Offers is an unknown, therefore I'm not sure how I can initialize a variable for each Offer in order to disable the button.
The task would be far more straight forward if I just had one single form, I colud set:
$scope.disableButton = true
... then use ng-disabled on the button
Thusfar I am displaying my forms as follows:
<div ng-form ng-repeat="i in offers track by $index" name="messageForm[$index]" class="row ng-cloak">
....
<button type="button" ng-click="offerRespond(messageForm[$index])" ng-disabled="!messageForm[$index].$valid || offer.i.disableButtons">Submit</button>
</div>
Then in my controller's offerRespond function:
offer = this;
offer.i.disableButtons = true;
This doesn't work of course but it is as close as I can get.
A hack would be to parse the Offers object before passing it to the frontend but that just seems like a horrible hack.
Actually I almost had the answer in my implementation, I just was referring to my variables in correctly:
ng-disabled="!messageForm[$index].$valid || offer.i.disableButtons"
should have been
ng-disabled="!messageForm[$index].$valid || i.disableButtons"
Thanks to #igor for giving me an idea to test which enabled me to revealed the answer myself.

Is there any way I can direct focus to a specific input field on a form?

I have a large form and I would like when the user clicks a "new" button for the focus to be placed in a specific input field. There's a grid on the form and every field has a known id. Note it might not be the first field so not easy to use the tab.
Would appreciate some advice if this is possible. Would save having to manually have the user move the cursor over and click in the input field.
Update: Changed "move cursor" to "change focus"
Here is one solution -
Angular js gives you an advantage of using some of the extra features so that you dont have to use the jquery.
Here is one way to implement the autofocus feature.
<div class="button" input-focus>{{element.idORname}}</div>
and the directive to be defined here.
.directive("inputfocus",function($timeout){
return {
link : function(element,attributes){
element.bind('click',function($timeout){
$timeout(function(){
element/*.parent() or.child()*/.find('type of the field you want to select')[0].focus();
);
);
);
Here you can use the javascript or jquery methods for the dom traversal if there are nested fields in your code.
$timeout is necessary to call for the focus after the browser renders when user has finished clicking the event
As you can see the find('')[0] is a replacement for find('').focus as the latter requires jquery to be used.
Place "autofocus" attribute on the element that you want to focus.
Example:
Name: <input type="text" name="name" autofocus />
If all the input ids are known, just use that.
$("#NewButton").on('click', function(){
//Other code.
$("#IdOfInputToBeFocused").focus();
});
Custom data attribute can be used with jQuery like this
<input data-field="special" />
And then that specific field can be called like this
jQuery('input').find("[data-field='special']").focus();

how to go from angular event to jquery selector

I know this is bad design but would like to introduce angular to a current project. I would like sayHello to be able to determine whether the element has the class 'is-a-favorite'
<div ng-click="sayHello(29, $event)" class="is-a-favorite" data-type="location" data-global-id="29" data-make-disappear="false"> </div>
$scope.sayHello=function(global_id,event){
//var selector=???
if(selector.hasClass('is-a-favorite')){
console.log("this is-a-favorite");
}
};
How would (or could) I get a reference to current DOM element to query via hasClass?
thx
The clicked element is available as $event.target, so you could check $($event.target).attr('class') or something similar.
EDIT: actually, what you'd want is to check $($event.target).hasClass('is-a-favorite')

What's a good way to control an angular-ui accordion programmatically?

I am using the accordion directive from http://angular-ui.github.com/bootstrap/ and I need to have more control over when the accordions open and close.
To be more precise I need a button inside the accordion-group that will close its parent accordion and open the next one (so basically mimic what clicking the next header would do if close-others was set to true).
I also need to do some validation before I can allow an accordion to be closed and the next one to be opened, and I also need to wire this up to click events on the accordion headers.
I am pretty new to angular and we're currently rewriting an application from Backbone+JQuery to Angular. In the Backbone-version we were using Twitter Bootstrap accordions and we were opening and closing them using JQuery. While we can still keep doing this I would rather get rid of JQuery DOM manipulation completely so I am looking for a pure angular solution to this.
What I've tried to do in terms of validation is
<accordion-group ng-click="close($event)">
and in my controller
event.preventDefault();
event.stopPropagation();
This obviously did not work as the DOM element is replaced by the directive and the click-handler is never added. I've been going over the source code (and found a few very nice undocumented features) but I'm at a loss over where to even begin solving this specific challenge. I was considering forking angular-ui and try to add this functionality to the accordion directive but if I can achieve this without modifying the directive that would be a lot nicer.
There is the is-open attribute on the accordion-group which points to a bindable expression. By using this expression you can control accordion items programatically, ex.:
<div ng-controller="AccordionDemoCtrl">
<accordion>
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
{{group.content}}
</accordion-group>
</accordion>
<button class="btn" ng-click="groups[0].open = !groups[0].open">Toggle first open</button>
<button class="btn" ng-click="groups[1].open = !groups[1].open">Toggle second open</button>
</div>
and the working plunk here: http://plnkr.co/edit/DepnVH?p=preview
For whoever the solution by #pkozlowski.opensource is not working (me for example) you could just force the component to accept the CSS that will close it (without transition that is).
The Theory: The angular directive gets expanded into standard HTML, div elements mainly, where the CSS styles give it the appearance of the accordion. The div with class .panel-collapse is the body of the accordion-group element. You can swap its second class from .in to .collapse along with a few other changes as seen below.
The Code:
$scope.toggleOpen = function(project) {
var id = '<The ID of the accordion-group you want to close>';
var elements = angular.element($document[0].querySelector('#'+id));
var children = elements.children();
for(var i = 0; i < children.length; i++) {
var child = angular.element(children[i]);
if(child.hasClass('panel-collapse')) {
if(child.hasClass('in')) { // it is open
child.removeClass('in');
child.addClass('collapse');
child.css('height', '0px');
} else { // it is closed
child.addClass('in');
child.removeClass('collapse');
child.css('height', 'auto');
}
}
}
};
As we are talking about Angular, it is very possible that you are generating the accordion through an ng-repeat tag. In this case you can also generate the id's for the elements like:
<accordion-group ng-repeat="user in users"
is-disabled="user.projects.length == 0"
id="USER{{user._id}}">
Given a Mongoose model User, notice that the id I am giving is not user._id but has 'USER' appended in front. This is because Mongoose might generate id's that start numerically and querySelector does not like that ;-) go figure!

Resources