I'm using mootools in 1 of my projects. I'm working on easy to be customised menu based on sortables.
So here's the issue - I've got the form which contains menu node informations. Form is updated with JS whenever user chooses different node (form is populated with new data). Problem is that "reset" button obviously "remembers" the initial data, so whenever user clicks it, it loads initial data form.
Is there anyway to update the "default" form status, whenever i load new data? (ofc i could write piece of code which do whatever i need, but if there is some simplier solution which allows default "reset" button to work with new data would be much less work to use it :))
Thanks in advance for help
i cant think of anything else except getting a new source through ajax with data prepopulated and replace the innerhtml hence replacing the form itself.
you can use something like toQueryString to serialize the form and then reverse it based upon the mootools-more's String.parseQueryString():
(function() {
Element.implement({
saveFormState: function() {
if (this.get('tag') !== 'form')
return;
this.store("defaults", this.toQueryString());
},
restoreFormState: function() {
if (this.get('tag') !== 'form')
return;
var vals = this.retrieve("defaults");
if (!vals.length)
return;
var self = this;
Object.each(vals.parseQueryString(vals), function(value, key) {
var el = self.getElement("[name=" + key + "]");
el && el.set('value', value);
});
}
});
})();
var f = document.id('f');
// save default
f.saveFormState();
document.getElement("button").addEvent("click", f.restoreFormState.bind(f));
this ough to cover most cases and you can always save a new defaults state. need to test it somewhat with radios and suchlike, though.
here's a basic fiddle with a save/restore: http://jsfiddle.net/UWTUJ/1/
relevant docs: http://mootools.net/docs/more/Types/String.QueryString (more) and http://mootools.net/docs/core/Element/Element#Element:toQueryString (core)
implied reliance on name attributes on all form elements you want to save/restore.
I have previously created more complex save/restore states that even return field CSS class names, validation messages, etc.
Related
(DISCLAIMER: I'm new to coding so my code probably isn't optimal. If you know a better way to do it, feel free to leave it in the comments )
Most of the time I had no idea what I was doing, but with patience and with you guys' help I came up with this:
if (window.localStorage) {
// Create the Key/Value
var cNum = localStorage.getItem("currentNumber");
if (localStorage.currentNumber == undefined) {
localStorage.setItem("currentNumber","0");}
// Variables
resetCount.innerHTML = localStorage.currentNumber;
// Functions
function btnR() {
cNum++;
localStorage.currentNumber = cNum;
resetCount.innerHTML = cNum;}}
else { console.log("No"); }
HTML:
<button id="resetButton" onclick="btnR()">Reset</button>
<p id="resetCount">0</p>
I was creating a button that each time you click on it, it reset the checkboxes, but I also wanted a counter to see how many times they got rested. The problem was that every time I click the button the counter also reset. Now that is solved I can try to apply the same thing for the checkboxes, so they don't reset on refresh either.
Note: I had to put the .SetItem in an if statement cause, even tho the value was in storage it kept setting back the value to zero every time I refreshed the page. This was the way I found to stop that.
You either need to set up a back end to send data to and save the information you want to keep stored, or save data in localStorage.
Just know it is not the best practice to save sensitive info in localStorage (as they can be compromised in cross-site scripting attacks).
localStorage.setItem puts a bit of data into localStorage (and that stays there till you clear it) and localStorage.getData extracts it.
This might help get you started on localStorage, but you will have to figure out the function to set the colour to the element you have.
let boxColour = localStorage.getItem("boxColour");
if (boxColour === null) {
setBoxColour("colour");
} else {
setBoxColour(boxColour);
}
function setBoxColour(colour){ localStorage.setItem("colour");}
/* Inside the function you have to get the item and change it's style attribute or add a class to add styles */
Careful with that localStorage data!
You could use LocalStorage.
It saves data in the page to be used after when the page is refreshed or closed and opened later.
Theres a example:
(Unfortunally, it seems to not work in the stackoverflow site, but if you try at your HTML file it will work)
var loadFunc = (elem) => {
console.log("Value saved is: "+ localStorage.getItem("savedValue"));
if(localStorage.getItem("savedValue")){ //checks if value is saved or not
elem.checked = localStorage.getItem("savedValue");
}
}
var clickFunc = (elem) => {
localStorage.setItem("savedValue", elem.checked); //set te value if in localStorage
}
Click the checkbox and the value will be saved.
<input type="checkbox" onload="loadFunc(this)" onclick="clickFunc(this)">
It has been 3 hours that I'm stuck.
I want to show up a pop up (a non-blocking one) when my condition is meet (_some field is equal something) while the user click the button "Save"on form view of record on sale.order model (only).The pop up should be triggered after the Save button peformed its default action because I need to check if the condition is meet in database.
I find here how to get a model.Models from javascript in Odoo.
I also find that I need to override the o_form_button_edit to make my change, but I don't know how to do that and I don't know if it has effect to other model because others use it.
this.$buttons.on('click', '.o_form_button_edit', this._onEdit.bind(this));
I wonder if my method is good to do that? If not can you suggest another one?
Can you help me? Thank you very much.
PS : I need a pop up because the user can Accept his change or Discard it when saving the record. If discard, I need to re-open o_form_button_edit if not, we do nothing because we already call the write method.
Here is a code snippet doing what you want:
var FormController = require('web.FormController');
var ExtendFormController = FormController.include({
saveRecord: function () {
var res = this._super.apply(this, arguments);
if(this.modelName == 'project.task'){
var self = this;
res.then(function(changedFields){
console.log(changedFields);
console.log(self.modelName);
self.do_notify('title', 'message');
// you can call a method on the server like this
self._rpc({
model: self.modelName,
method: 'search_read',
fields: ['name'],
context: self.context,
}).then(function(result){
console.log('rpc result');
console.log(result);
})
});
}
return res;
}
});
A screenshot just after I clicked Save:
You also need to inherit the createRecord() method the same way.
A few notes:
the first console log line saying: ["name"] is the value of changedFields (I only changed the name of the task before hitting Save)
I was working on the project.task object but you can change that to sale.order :)
The official documentation is very helpful
I have purchased a booking plugin (wordpress) to add to a site.
https://wpamelia.com/
I cannot show the site I am working on, but here a demo from plugin developers
https://sports.wpamelia.com/#book
Once you have chosen your date and time, you end up on a form with input fields.
I was able to pre-fill this form with data that I could pass via the URL.
My URL would look something like this: https://sports.wpamelia.com/?first=Jim&last=Tester&email=something%40something.com&phone=0222222222#book
But here is the problem:
Even though I managed to use jQuery to pre-fill the input fields of the form, as soon as I click confirm the fields' content is erased and the error "Please enter... " appears for each of them.
So again:
STEP 1: I open the booking page with an URL containing data in the query string
STEP 2: Using jQuery, I manage to pre-fill the form that appears after having chosen date and time (first name, last name ...)
STEP 3: I click "Confirm"
RESULT: all the fields are empty and for each one the error message "Please enter first name" (etc..) appears
I've messaged the plugin developers. Only answer was that there is indeed no functionality to take the data from the Query String into the form fields yet.
MY QUESTIONS:
1) How could I find out, with chrome inspector or other tools, why exactly the content I pre-fill into the form is ignored?
---> I've tried things like getEventListeners in the chrome inpector's console, but I don't really see how to get information out of that
2) Would anyone know what the issue is and/or how I could bypass it?
---> there is a lot of javascript from the plugin developers behind that and something is expecting manual entering of the data into the fields...
---> but even when trying to fake manual entering with things like $(this).trigger("change").val(function(i,val){return 'aaaa';}); this didn't solve the problem....
(If anyone is interested, I can post later my javascript/jQuery functionality to get the form fields pre-filled with data from Query String... interesting code as you have to wait until the fields appear for jQuery to recognise them..)
Thanks so much for any help!
cheers
Admino
#Admino - this may not be the best solution and I know this is an old question so you may not need it now but after not finding a better one it at least worked for me.
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
function valueOutput(element) {
element.dispatchEvent(new Event('input'));
}
jQuery(function() {
jQuery(document).on('change', 'input', function(e) {
valueOutput(e.target);
});
// you may want to perform more validations here if needed
// just checking here if email is present (but not checking for valid email address)
var fname = getUrlVars()["first"];
var lname = getUrlVars()["last"];
var email = getUrlVars()["email"];
var phone = getUrlVars()["phone"];
var custom1 = getUrlVars()["custom1"]; // you know this field label is Order Number
if (email.length > 0) {
// run an interval until the elements are present on the page (form displayed)
var checkInputs = setInterval(function() {
if (jQuery('.amelia-app-booking label[for="customer.email"]').length > 0) {
var em = jQuery('.amelia-app-booking label[for="customer.email"]').closest('.el-form-item').find('.el-input__inner');
// this checks to see if an Amelia customer is already present
if (em.val() == '') {
em.prop('value', email).val(email).trigger('change');
jQuery('.amelia-app-booking label[for="customer.firstName"]').closest('.el-form-item').find('.el-input__inner').prop('value', fname).val(fname).trigger('change');
jQuery('.amelia-app-booking label[for="customer.lastName"]').closest('.el-form-item').find('.el-input__inner').prop('value', lame).val(lame).trigger('change');
jQuery('.amelia-app-booking label[for="customer.phone"]').closest('.el-form-item').find('.el-input-group__prepend').siblings('.el-input__inner').prop('value', phone).val(phone).trigger('change');
}
// for custom fields I check the label text to find the correct input
if (custom1 != '') {
jQuery('.amelia-app-booking label:contains("Order Number")').closest('.el-form-item').find('.el-input__inner').prop('value', custom1).val(custom1).trigger('change');
}
// form info is updated so clear the interval
clearInterval(checkInputs);
}
}, 500);
}
});
You may want to try a different method than url params to sync this info so it's not so public in the url string. This code may not need both the prop and val jquery setters but I just left them for you to try. Hope it helps (and to others I'm open to a better solution)!
I am at the very beginning with my Angular learning and I implemented this form:
http://codepen.io/jgrecule/pen/WxgqqO
What it is supposed to do is very basic: it consumes Flickr public JSONP feed as per Flicker specs https://www.flickr.com/services/feeds/docs/photos_public/ and renders the retrieved pictures thumbnails
The form I implemented has a submit button as well as a reset one. My problems I am trying too find solutions in the order of their importance are:
The very first time when you typing tags everything works but when u try to submit the request again by either adding a new tag or an user Id or anything it no longer works. I can see this warning in the logs but I have no idea what is causing it WARNING: Tried to load angular more than once.
The reset only works for the thumbnails but not for the other controls in my page
I would like to find a way to show an error message when the user pushes on the search flicker button and both tags and user ids input fields are empty. I tried to implement a custom directive but it was no way to get it working.
Thank you in advance for your inputs.
You are loading Angular more than once.
Your resetForm function doesn't reset the form at all. It just calls $setValidity on two of the form elements. It looks like it does try and reset the form in another part of your code with
document.getElementById("searchCriteriaTags").innerHTML = "";
document.getElementById("searchCriteriaIds").innerHTML = "";
document.getElementById("images").innerHTML = "";
which means you are modifying the DOM directly, about which see point 4.
You can add a simple check as to whether $scope.form.tags === '' and so the same for the other fields in your form.
Having addressed your 3 points, I'm afraid to say your code has bigger problems. You are modifying the DOM directly all over the place and you have a lot of duplicate code, plus lots of very complex conditionals.
EDIT 1 in response to OP's comment:
The Angular way of clearing form fields would be to simply clear the scope objects that the form fields are bound to. In other words it is as simple as doing something like:
$scope.tags = [] // for arrays
$scope.name = '' // for strings
Because the form fields are bound to these scope variables through the ng-model directive, changing the variables will also change the form fields.
Setting an error message when two fields are empty you can do like this:
$scope.checkFields = function(field1, field2) {
var oneEmpty = field1 === '';
var twoEmpty = field2 === '';
if (oneEmpty && twoEmpty) {
// call the failure message here
}
}
EDIT 2 in response comments:
Firstly good to see that your code is looking a lot cleaner. Secondly, the reason it fails is because in your search function you set the search fields to null, eg searchCriteria.tags = null;. You should set them to empty strings instead: searchCriteria.tags = '';.
I don't know what the purpose of checkFields is so I don't know where you want to place it. If you want to show an error message if the fields are empty then I'd say have checkFields() return a boolean and use ng-show to display the error div if checkFields() === false.
HTML:
<div ng-show="checkFields() === false">Fields can't be empty</div>
JS:
$scope.checkFields = function(field1, field2) {
var oneEmpty = field1 === '';
var twoEmpty = field2 === '';
return (oneEmpty || twoEmpty);
}
I have this fiddle: http://jsfiddle.net/y8Uju/5/
I am trying to save the numbers, because, when I submit, the list of numbers gets erased. I am a little new to JavaScript so am not quite familiar to what is available. In PHP I would use sessions to save the list, but what can I do in JavaScript to do this?
Here is the JavaScript code:
function bindName() {
var inputNames = document.getElementById("names").getElementsByTagName("input");
for (i = 0; i < inputNames.length; i++) {
inputNames[i].onkeydown = function() {
if (this.value == "") {
setTimeout(deletename(this), 1000);
}
}
}
}
document.getElementById("addName").onclick = function() {
var num1 = document.getElementById("name");
var myRegEx = /^[0-9]{10}$/;
var itemsToTest = num1.value;
if (myRegEx.test(itemsToTest)) {
var form1 = document.getElementById("names");
var nameOfnames = form1.getElementsByClassName("inputNames").length;
var newGuy1 = document.createElement("input");
newGuy1.setAttribute("class", "inputNames");
newGuy1.setAttribute("id", nameOfnames);
newGuy1.setAttribute("type", "text");
newGuy1.setAttribute("value", num1.value);
form1.appendChild(newGuy1);
num1.value = "";
bindName();
}
else {
alert('error');
}
};
function deletename(name) {
if (name.value == "") {
document.getElementById("names").removeChild(name);
}
}
You can use localStorage: http://jsfiddle.net/y8Uju/8/
Loading:
var saved = JSON.parse(localStorage["numbers"] || "[]");
for(var i = 0; i < saved.length; i++) {
document.getElementById("name").value = saved[i];
add(false);
}
Saving:
var saved = JSON.parse(localStorage["numbers"] || "[]");
saved.push(num1.value);
localStorage["numbers"] = JSON.stringify(saved);
And define the function of the addName button separately, so that you can call it when loading as well.
Edit: You have to execute a function when the page is loading to fetch the stored numbers, and add some code to save the entered number when one clicks the Add button.
For storing you can use localStorage, but this only accepts Strings. To convert an array (an array containing the entered numbers), you can use JSON.
When loading, you need to add the numbers just like happens when the user fills them in. So you can set the name input box value to the saved number for each element in the array, and then simulate a click on the Add button.
So you need an add function that is executed when:
User clicks Add button
Page is loaded
However, when simulating the click the numbers should not get stored again. You need to distinguish between a real click and a simulated one. You can accomplish this by adding an argument to the add function which represents whether or not to store.
Not entirely sure what the question is, but one problem I see with the code - id's can't be numbers, or start with numbers
var nameOfnames = form1.getElementsByClassName("inputNames").length;
//....
newGuy1.setAttribute("id", nameOfnames);
That might be slowing you down somewhat. Perhaps set id to 'newguy' + nameOfnames
Jeff, the reason that the page keeps getting erased is because the form submission triggers a page reload. You need to place a listener on the form submit event and then send the data through AJAX. This way the data is POSTed to "text.php" without reloading the page with the form.
You could place the values in a cookie but that is not ideal because you have a fairly limited amount of space to work with (4kb). I also get the feeling that you're trying to hand them off to some server side script so HTML5 local storge wouldnt be a good solution, not to mention that your eliminating over half of the people on the internet from using your site that way.
Since browsers are inconsistent in how they attach event listeners AND how they make AJAX requests. I think that most people would recommend that you use a library like jQuery, dojo, or prototype which abstract the process into one function that works in all browsers. (my personal fav is jQuery)
There are a few options available to you:
Save it client side using cookies (http://www.quirksmode.org/js/cookies.html)
Save it client side using HTML5 local storage (http://diveintohtml5.ep.io/storage.html)
Save it server-side using Ajax
The Ajax solution involves a server side page (in PHP for example) that reads a request (a POST request for example) and saves it into a database or other. You then query that page in JavaScript using XmlHTTPRequest or your favorite library.