We have a submit binding in knockout, however we can use it only on whole form, so in a case of multiple submit buttons, they all trigger same binding. I'd like differ action for each one, but idk how to differ which one has been clicked, eg.:
HTML:
<form data-bind="submit: save">
<input type=submit name=save value=Save>
<input type=submit name=saveAndClose value="Save & close">
</form>
VM:
var ViewModel = function () {
this.save = function (form) {
var clicked = 'how to find out?';
if (clicked === 'save') {
// save
} else if (clicked === 'saveAndClose') {
// save
// close
}
};
};
Yea, I can use click binding on each submit, but then there's no form element available, yea - I can obtain it by different way, but maybe you know better solution.
Do you?
Well, what you can do is to use a click binding on each input and pass a $element variable as a parameter. As such:
<form>
<input type=submit name=save data-bind="click: save.bind(null, $element)" value=Save>
<input type=submit name=saveAndClose data-bind="click: save.bind(null, $element)" value="Save & close">
</form>
bind in javascript creates a new function with a specified this (null) and parameter ($element) in this case. Therefore, it is easy to obtain a form element, and determine which input was clicked:
var ViewModel = function () {
this.save = function (el) {
var clicked = el.getAttribute('name');
var form = el.parentElement;
console.log(clicked, form)
if (clicked === 'save') {
// save
} else if (clicked === 'saveAndClose') {
// save
// close
}
};
};
Working fiddle
Note however, that this method is markup dependent, if the inputs are not direct children of the form element, you may need to find another method to get the form element itself instead of parentElement
Overload submit binding to allow use it on any element.
JSFiddle: Knockout submit binding applicable onto any button (uses jQuery)
Binding overload:
var overridden = ko.bindingHandlers.submit.init;
var $clickedButton;
ko.bindingHandlers.submit.init = function (element, valueAccessor) {
var $form = $(element);
if ($form.prop('tagName') !== 'FORM') {
var $button = $form;
$form = $form.closest('form');
if ($form.length === 0) {
throw new Error('Submit binding can be used only in forms');
}
$button.on('click', function () {
$clickedButton = $button;
});
var formHandler = function () {
return function () {
if ($clickedButton === $button) {
return valueAccessor().apply(this, arguments);
}
return false;
};
};
overridden.apply(this, [$form[0], formHandler].concat([].splice.call(arguments, 2)));
} else {
overridden.apply(this, arguments);
}
};
ViewModel:
var ViewModel = {
submitA: function () {
alert('A');
},
submitB: function () {
alert('B');
}
};
ko.applyBindings(ViewModel);
HTML:
<form method=post>
<input type=submit data-bind="submit: submitA" value=A>
<input type=submit data-bind="submit: submitB" value=B>
</form>
Related
I am trying to have a checkbox update the value of an observable. This partially works, but the checkbox does not "check" itself after. To solve this I tried to add the checked: binding, looking for the value that I had just set in the click event, but this also does not work.
My Observable
appViewModel.test = ko.observable(1);
The checkbox
<input type="checkbox" data-bind="checked: test() == 4, click: test.bind($data, 4)"/>
You can write a click handler that checks to see if the value is 4 (or whatever arbitrary value you want) and then can act accordingly, like this:
HTML:
<input type="checkbox" data-bind="checked: checkBoxValue() === 4,
click: handleCheckBoxClick">
<br/>
<div>
<span>Debug:</span>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
</div>
JavaScript:
var ViewModel = function () {
var self = this;
self.checkBoxValue = ko.observable(0);
self.handleCheckBoxClick = function () {
if (self.checkBoxValue() !== 4) {
self.checkBoxValue(4);
} else {
self.checkBoxValue(0);
}
return true;
};
};
ko.applyBindings(new ViewModel());
Note: I added the debug output so you could see the underlying checkBoxValue value in the view model as you interact with the checkbox.
See jsFiddle here
You can use a computed to catch observable changes:
var ViewModel = function(first, last) {
var self = this;
this.checked = ko.observable(false);
this.test = ko.observable();
this.isChecked = ko.computed(function(){
var test = self.test();
if(test === '4')
{
self.checked(true);
return;
}
self.checked(false);
});
};
Here is a jsfiddle
The checked binding wants to be two-way, writable as well as readable. It can't write to a test, though, when you click it. Instead of having a click binding, you should have the test set to 4 by the write function of the computed you use as the checked binding.
var vm = {
test: ko.observable(1)
};
vm.checked = ko.computed({
read: function () { return vm.test() == 4; },
write: function (newValue) {
vm.test(newValue ? 4 : 1);
}
});
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="checkbox" data-bind="checked: checked"/>
<div data-bind="text:test"></div>
i have a script which check when two textfields are not empty it does automatic submission. it picks the variables from the localstorage and places them in the textfields.
if (localEmail != null && localPwd != null) {
$('#form1').submit();
}
and i also i have a script which disables the submit button when all textfields are not filled.
$(document).ready(function (){
var $input = $('#form1 input:text'),
$register = $('#button_id');
$register.attr('disabled', true);
$input.keyup(function() {
var trigger = false;
$input.each(function() {
if (!$(this).val()) {
trigger = true;
}
});
trigger ? $register.button('disable') : $register.button('enable');
});
});
now my problem is when the page loads for the second and subsequent times and there are variables from the localstorage in the textfields, the submit button still remains disabled and the automatic submission fails. Now i want the button to remain active when there are variable in it so the automatic submission can be done
In document ready do an additional check for input values and disable the button
$(document).ready(function () {
var $input = $('#form1 input:text'),
$register = $('#button_id');
$input.each(function () {
if (!$(this).val()) {
$register.attr('disabled', true);
return false;
}
});
$input.keyup(function () {
var trigger = false;
$input.each(function () {
if (!$(this).val()) {
trigger = true;
}
});
trigger ? $register.attr('disabled', true) : $register.removeAttr('disabled');
});
});
$(document).ready(function () {
var $input = $('#form1 input:text'),
$register = $('#button_id');
$input.each(function () {
if (!$(this).val()) {
$register.attr('disabled', true);
return false;
}
});
$input.keyup(function () {
var trigger = false;
$input.each(function () {
if (!$(this).val()) {
trigger = true;
}
});
trigger ? $register.attr('disabled', true) : $register.removeAttr('disabled');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<form id="form1">
<input type="text" />
<input type="text" />
<button id="button_id">button</button>
</form>
The reason why you are not achieving the desired behavior is because you are only updating the button's disabled property when a change event is fired from the input element(s), which are not fired by default upon page load.
The solution is to therefore move the function involving updating the button's status into a separate one, which we will call upon runtime (e.g. DOM ready) and then again when the change event is fired on element(s) of interest:
var updateButton = function() {
var trigger = false;
$input.each(function() {
if (!$(this).val()) {
trigger = true;
}
});
trigger ? $register.button('disable') : $register.button('enable');
};
// Update button status on DOM ready
updateButton();
// Update button status on keyup
$input.keyup(updateButton);
On a side note, please use .prop() when dealing with binary attributes:
$register.prop('disabled', true);
this should work
$input.each(function() {
if (!$(this).val()) {
trigger = true;
}
under document ready function.
$(document).ready(function (){
var $input = $('#form1 input:text');
$register = $('#button_id');
$register.prop('disabled', true);
//$register.attr('disabled', true);
$('#button_id').on('click',function(){alert('hi');});
function checkInputs(){
$input.each(function(e) {
if (!$(this).val().length < 1) {
trigger = true;
} else
{trigger = false;}
});
trigger ? $register.prop('disabled',false) : $register.prop('disabled',true);
}
checkInputs();
$('#form1 input:text').on('keyup',function(){checkInputs();});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form1">
<input/>
<input />
<button type="button" id="button_id" >Submit</button>
</form>
I have this code:
<script type="text/javascript">
function changestate()
{
var StateTextBox = document.getElementById("State");
var IgnoreTextBox = document.getElementById("Ignore");
var PlayButton = document.getElementById("Play");
if(document.getElementById("Play").onclick == true)
{
StateTextBox.value = "Happy";
}
}
</script>
<input TYPE="button" VALUE="Play with Pogo" id="Play" onClick="changestate();"/>
I'm trying to know when the button is clicked, and have that if button is clicked in the if statement. I want to know this so I can change the value that is inside the text box. The problem is, I do not know how to tell when the button is clicked. If you could help me out that would be great.
The onclick attribute identifies what should happen when the user clicks this particular element. In your case, you're asking that a function be ran; when the function runs, you can rest assured that the button was clicked - that is after all how the function itself got put into motion (unless you invoked it some other way).
Your code is a bit confusing, but suppose you had two buttons and you wanted to know which one was clicked, informing the user via the stateTextBox value:
(function () {
// Enables stricter rules for JavaScript
"use strict";
// Reference two buttons, and a textbox
var playButton = document.getElementById("play"),
stateTextBox = document.getElementById("state"),
ignoreButton = document.getElementById("ignore");
// Function that changes the value of our stateTextBox
function changeState(event) {
stateTextBox.value = event.target.id + " was clicked";
}
// Event handlers for when we click on a button
playButton.addEventListener("click", changeState, false);
ignoreButton.addEventListener("click", changeState, false);
}());
You can test this code live at http://jsfiddle.net/Y53LA/.
Note how we add event-listeners on our playButton and ignoreButton. This permits us to keep our HTML clean (no need for an onclick attribute). Both of these will fire off the changeState function anytime the user clicks on them.
Within the changeState function we have access to an event object. This gives us some details about the particular event that took place (in this case, the click event). Part of this object is the target, which is the element that was clicked. We can grab the id property from that element, and place it into the value of the stateTextBox.
Here is the adjusted HTML:
<input type="button" value="Play with Pogo" id="play" />
<input type="text" id="state" />
<input type="button" value="Ignore with Pogo" id="ignore" />
You can know if button clicked by using a flag (true or false).
var flag = false;
window.addEventListener("load", changestate, false);
function changestate() {
var StateTextBox = document.getElementById("State");
var PlayButton = document.getElementById("Play");
PlayButton.addEventListener("click", function () {
flag = true;
})
PlayButton.addEventListener("click", change)
function change() {
if (flag) {
StateTextBox.value = "Happy";
}
}
}
Looking back on this, many years later, you could simply do:
<script type="text/javascript">
function changestate(action)
{
var StateTextBox = document.getElementById("State");
var IgnoreTextBox = document.getElementById("Ignore");
var PlayButton = document.getElementById("Play");
if(action == "Play")
{
StateTextBox.value = "Happy";
}
}
</script>
<input TYPE="button" VALUE="Play with Pogo" id="Play" onClick='changestate("Play");'/>
After clicking on Add Input and adding an input, clicking on the added button doesn't call the required_valid() function in $('.submit').submit(function () {.... Why is this?
DEMO: http://jsfiddle.net/Jvw6N/
Add Input
<div class="get_input"></div>
$('.add_input').live('click', function(e){
e.preventDefault();
$('.get_input').append('<form class="submit"><input name="test" class="required"> <br /> <button>Click Me</button></form>')
})
function required_valid() {
var result = true;
$('.required').each(function () {
if (!$(this).val()) {
$(this).css("background", "#ffc4c4");
result = false;
}
$(this).keyup(function () {
$(this).css("background", "#FFFFEC");
})
});
return result;
}
$('.submit').submit(function () {
var passed = true;
//passed = required_selectbox() && passed;
passed = required_valid() && passed;
if (!passed) {
$('#loadingDiv, #overlay').hide();
return false;
}
});
You need to set up your "submit" handlers with ".live()" (or ".delegate()" or the new ".on()") just like your "addInput" button:
$('body').delegate('.submit', 'submit', function() {
// your submit code here
});
You're adding those forms dynamically, so your handler isn't actually bound to any of them.
Alternatively, you could bind the handler when you add the form.
I have this function:
$(document).ready(function(){
function Fos(buttonSel, inputSel, someValue, cssProperty) {
$(buttonSel).click(function(){
var value = $(inputSel).attr("value");
$("div.editable").click(function (e) {
e.stopPropagation();
showUser(value, someValue, this.id)
var css_obj={};
css_obj[cssProperty]=value;
$(this).css(css_obj);
});
});
}
Here are three places where function is written:
Fos('#border_button', '#border-radius', 2, '-webkit-border-radius');
Fos('#background_color_button', '#background-color', 1, 'background-color');
Fos('#opacity_button', '#opacity', 3, 'opacity');
<input type="text" id="border-radius" value="20px">
<div id="border_button">BORDER RADIUS</div>
<input type="text" id="background-color" value="red">
<div id="background_color_button">Background</div>
<input type="text" id="opacity" value=".5">
<div id="opacity_button">Opacity</div>
<div id="2" class="defaultclass editable" style="<?php getStyle('2') ?>">
something
</div>
When you click the DIV with the ID= "border_button", or "background_color_button", or "opacity_button"
it waits for you to click any DIV with class="editable", ...$("div.editable").click(function (e) {... it executes the function with those parameters.
I just need a fix that will only allow ONE function with the parameters to be enabled at one time.
Currently, when you click on all three divs with ID = "border_button", or "background_color_button", or "opacity_button" AND THEN on a div with class="editable", it executes the function with ALL THREE sets of parameters.
This is bad. I can't figure it out.
You can't "disable" a function, but you can set a variable that will force it to exit right away:
var stopMe = true
function myFunction() {
if(stopMe) {
return;
}
...
}
You seem to be binding and rebinding the same functions over and over, which is probably why you have that e.stopEventPropagation in there. Try assigning the events once and then managing the current state (which button is active) and going from there:
var $currentInput = null;
$("#border_button,#background_color_button,#opacity_button").click(function() {
if ($currentInput == null) {
$currentInput = $(this).prev();
}
});
$("div.editable").click(function(e) {
if ($currentInput == null)
return;
$(this).css(GetCssProperties());
showUser($currentInput.val(), /* where does someValue come from? */, this.id)
$currentInput = null;
});
function GetCssProperties() {
if ($currentInput == null) return null;
var value = $currentInput.val();
if ($currentInput.attr("id") == "border-radius") return {
"-webkit-border-radius": value
}
if ($currentInput.attr("id") == "background-color") return {
"background-color": value
}
if ($currentInput.attr("id") == "opacity") return {
"opacity": value
}
}
working example here: http://jsfiddle.net/HUJ5A/
Run the function for tag with a specific class. And a the end of the function remove this class from the tag.
jQuery(".myclass").click(function(){
/* do something */
jQuery(this).removeClass('myclass');
});
Can't tell everything from your question. But this part $("div.editable").click(function (e) { will bind multiple click events to div.editable each time the user clicks Foo arugments[0] or buttonSel.
This could be a pssible solution:
Have a global variable (or HTML hidden input) say, lastDivClicked, to store the id of the recently clicked div
Update lastDivClicked everytime one of those three divs are clicked upon
Change your function to this:
function Fos(inputSel, someValue, cssProperty) {
var buttonSel = $('#lastDivClicked').val();
$(buttonSel).click(function(){ ... }
}