I have a script that handles a semi-complex contact form. The site is built using a website building platform called Duda and I think there may be timing issues as they load a bunch of scripts of their own. Anyway I'm getting a ReferenceError: price is not defined, error.
Price gets called onChange on inputs, for example:
<input value="Yes" name="dmform-9" type="radio" id="watch-me-hide" checked="checked" onchange="price()"/>
The script works sometimes, then other times not. Very frustrating. Does anyone know how to make sure that my functions get loaded in this situation?
Here is the whole script:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
var counter = 0;
$(document).ready(function() {
$("input[type="radio"]").click(function() {
alert("here");
var ids = ["#occupiedBy", "#nameOccupied", "#phoneOccupied", "#mobileOccupied", "#emailOccupied"];
if($(this).attr("id") == "watch-me-hide" || $(this).attr("id") == "watch-me-show") {
if ($(this).attr("id") == "watch-me-hide") {
$("#show-me").hide();
ids.forEach((id) => $(id).prop("required", false));
}
else if ($(this).attr("id") == "watch-me-show"){
$("#show-me").show();
ids.forEach((id) => $(id).prop("required", true));
}
else {
}
} else if($(this).attr("id") == "hideShowInDepth-hide" || $(this).attr("id") == "hideShowInDepth-show") {
if ($(this).attr("id") == "hideShowInDepth-hide") {
$("#moreRooms").hide();
price(null);
ids.forEach((id) => $(id).prop("required", false));
}
else if ($(this).attr("id") == "hideShowInDepth-show"){
$("#moreRooms").show();
price(null);
ids.forEach((id) => $(id).prop("required", true));
}
}
else{
}
});
};
function price() {
var priceIncrement = 70;
var minimumPrice = "189.00";
var basic = document.getElementById("hideShowInDepth-hide");
var advanced = document.getElementById("hideShowInDepth-show");
var ids = ["numberAdditionalRooms", "numberLaundries", "bedrooms", "numberLounges", "numberDining", "numberKitchens", "numberBathrooms", "numberHallways", "numberGarages"];
if ((basic.checked == true) && (advanced.checked == false)) {
/* Get number of rooms for basic inspection */
var e = document.getElementById("bedrooms");
var numberOfBedrooms = e.options[e.selectedIndex].value;
if (numberOfBedrooms == 0){
document.getElementById("totalPrice").textContent = "0.00";
}
else if ((numberOfBedrooms <= 3) && (numberOfBedrooms >= 1)){
document.getElementById("totalPrice").textContent = minimumPrice;
}
else if ((numberOfBedrooms <= 6) && (numberOfBedrooms >= 3)){
document.getElementById("totalPrice").textContent = "259.00";
}
else if (numberOfBedrooms > 6){
document.getElementById("totalPrice").textContent = "329.00";
}
else {
alert("Script error: Undefined number of bedrooms")
}
return false;
}
else if ((basic.checked == false) && (advanced.checked == true)) {
/* Get number of rooms for advanced inspection */
ids.forEach(logArrayElements);
if (counter == 0){
document.getElementById("totalPrice").textContent = "0.00";
}
else if (counter == 1){
document.getElementById("totalPrice").textContent = minimumPrice.toFixed(2);
;
}
else {
var money = ((counter * priceIncrement) + +minimumPrice) - +priceIncrement;
document.getElementById("totalPrice").textContent = money.toFixed(2);
}
counter=0;
return false;
}
else if ((basic.checked == false) && (advanced.checked == false)) {
alert("Script error: Neither checkbox is checked");
return false;
}
else if ((basic.checked == true) && (advanced.checked == true)) {
alert("Script error: Both checkboxes are checked");
return false;
}
else{
alert("Script error: Unknown error");
return false;
}
}
function logArrayElements(element, index, array) {
// alert("a[" + index + "] = " + element + " - " + value);
var e = document.getElementById(element);
var strUser = e.options[e.selectedIndex].value;
counter = +counter + +strUser;
}
</script>
watch-me-hide and watch-me-show are radio buttons that when changed they hide or show another section of the contact form to fill out, and make the inputs required or not.
hideShowInDepth-hide and hideShowInDepth-show are the same, but for another div section.
the price function updates the text in a span to reflect a new price when an input value has changed.
price() gets called onchange of dropdowns and radio buttons.
Any help appreciated.
Related
I'm a beginner to JavaScript. Can someone help me in this regard?
In the below code the logic for submit button doesn't work. _btn.addEventListener. Only the if part is getting executed, some issue with the else part condition. If the "if" condition gets satisfied then the alert is getting executed and not the conditions in else part even if the date and image is clicked.
<p align=center>
<input type="submit" value="submit" id="button">
</p>
<script type="text/javascript">
let _img = document.getElementById("img");
let _img1 = document.getElementById("img1");
let _img2 = document.getElementById("img2");
let _picker = document.getElementById("picker");
let _btn = document.getElementById("button");
let isImgClicked = false;
let isDatePicked = false;
/*let ImgClicked = '_img';
let ImgClicked1 = '_img1';
let ImgClicked2 = '_img2';
let DatePicked = '2019';
let DatePicked1 = '2020';*/
_img.addEventListener("click", function(){
isImgClicked = true;
ImgClicked=true
});
/*_img1.addEventListener("click", function(){
ImgClicked1 = true;
});
_img2.addEventListener("click", function(){
ImgClicked2 = true;
}); */
_picker.addEventListener("click", function(){
isDatePicked = true;
});
_btn.addEventListener("click", function(){
if(!isImgClicked || !isDatePicked)
{
alert("select the Year and Click the car image");
}
else
{
if((isImgClicked == "_img") && (isDatePicked == "DatePicked"))
{
window.location.replace("sample1.html");
}
else if((isImgClicked == "_img") && (isDatePicked == "DatePicked1"))
{
window.location.replace("sample2.html");
}
else
{
if((isImgClicked == "_img1") && (isDatePicked == "DatePicked"))
{
window.location.replace("sample3.html");
}
else if((isImgClicked == "_img1") && (isDatePicked == "DatePicked1"))
{
window.location.replace("sample4.html");
}
else
{
alert("!!!!");
}
}
}
});
</script>
Here you are assigning isImgClicked = true and ImgClicked = true
img.addEventListener("click", function(){
isImgClicked = true;
ImgClicked=true
});
But you are comparing this boolean with strings. Why?
if((isImgClicked == "_img1") && (isDatePicked == "DatePicked1"))
Fix it.
This is your function re-written in early-return style:
function() {
if(!isImgClicked || !isDatePicked) {
alert("select the Year and Click the car image");
return
}
if((isImgClicked == "_img") && (isDatePicked == "DatePicked")) {
window.location.replace("sample1.html");
return
}
if((isImgClicked == "_img") && (isDatePicked == "DatePicked1")) {
window.location.replace("sample2.html");
return
}
if((isImgClicked == "_img1") && (isDatePicked == "DatePicked")) {
window.location.replace("sample3.html");
return
}
if((isImgClicked == "_img1") && (isDatePicked == "DatePicked1")) {
window.location.replace("sample4.html");
return
}
alert("!!!!");
}
Which if statement are you having a problem with?
I am a very new programmer, and im not used to things more complex than a few if else statements or some light DOM traversing.
With the help of stackoverflow I've created a test for an RPG website im building.
14 questions test the users "concerns" as a player in a dungeons and dragons like setting, and assign points to 1 of 8 personality types.
Each of the 8 types, are the properties of two objects. PrimaryResults and secondaryResults. Each of the 8 properties have the same name.
Defender (def) , Berserker(ber), Monk(mnk) etc (you'll see it in the code)
The point is to be able to get results like Def/Def or Ber/Def or Mnk/Def
there are 8x8 combinations or 64 results.
then one div with the a class of results appends the actual HTML results to the screen for the user based on the final scores of the test.
My Problem:
I need a line of Code that goes through each property of BOTH objects and finds the highest value, I'm trying to put that in an IF statement that results in appending the correct results to the user.
Updated Attempt on 6/5 ---
USing Azamantes' code suggestion, I find that I still get the results of DEF/ DEF no matter what the actual values of each variable are.
I've included a screen shot of what the console.log is telling me about the values vs what the display is bringing up.
For some reason when the code cycles over
If ph =def and sh = def its coming back as true.
In the image I circled a possible issue, I dont know im not an expert.
could it having anything to do with how it says 0 for Ber on the top and has the score for ber when clicked on ? (see picture)
or could it have anything to do with the values of the objects itself? Are the values getting lost in translation somewhere?
$(window).load(function() {
$(".intro").appendTo('#display_box');
var question = $(".question");
var questionPosition = -1;
var results =$(".results");
var secondaryResults = {
def:0,
ber:0,
mnk:0,
rng:0,
cle:0,
thf:0,
mge:0,
dru:0,
};
var primaryResults = {
def:0,
ber:0,
mnk:0,
rng:0,
cle:0,
thf:0,
mge:0,
dru:0,
};
let pH = 'def', sH = 'def';
Object.keys(primaryResults).map(key => {
if(primaryResults[key] > primaryResults[pH]) {
pH = key;
}
if(secondaryResults[key] > secondaryResults[pH]) {
sH = key;
}
});
const highestPrimary = primaryResults[pH];
const highestSecondary = secondaryResults[sH];
$("#submit").on('click', function(){
console.log(primaryResults);
console.log(secondaryResults);
if (pH == 'def' && sH == 'def') {
clearBox();
results.eq(0).fadeIn(500).appendTo('#display_box');
};
if (pH == 'def' && sH == 'ber') {
clearBox();
results.eq(1).fadeIn(500).appendTo('#display_box');
};
if (pH == 'def' && sH == 'mnk') {
clearBox();
results.eq(2).fadeIn(500).appendTo('#display_box');
};
if (pH == 'def' && sH == 'rng') {
clearBox();
results.eq(3).fadeIn(500).appendTo('#display_box');
};
if (pH == 'def' && sH == 'thf') {
clearBox();
results.eq(4).fadeIn(500).appendTo('#display_box');
};
if (pH == 'def' && sH == 'cle') {
clearBox();
results.eq(5).fadeIn(500).appendTo('#display_box');
};
if (pH == 'def' && sH == 'dru') {
clearBox();
results.eq(6).fadeIn(500).appendTo('#display_box');
};
if (pH == 'def' && sH == 'mge') {
clearBox();
results.eq(7).fadeIn(500).appendTo('#display_box');
};
})
function clearBox(){
$("#display_box").children().fadeOut(500).appendTo('#question_holding');
};
function cycle(){
question.eq(questionPosition).fadeIn(500).appendTo("#display_box");
$("#display_box").animate({scrollTop:0}, 500);
}
$('#leftarrow').on('click', function(){
questionPosition--;
if (questionPosition <= -1) {questionPosition = 13};
clearBox();
cycle();
});
$('#rightarrow').on('click', function(){
questionPosition++;
if (questionPosition > 13) { questionPosition = 0};
clearBox();
cycle();
if($('input[name^="answer"]:checked').length > 13 ) {
$("#submit").css('display', 'block');
}
});
$('#submit').on('click', function() {
$('input[name^= "answer"]:checked').each(function(){
if ($(this).val() == "monkL"){
secondaryResults.mnk += 1.02;
}
if ($(this).val() == "berserkerL"){
secondaryResults.ber += .99;
}
if ($(this).val() == "defenderL"){
secondaryResults.def += 1.01;
}
if ($(this).val() == "thiefL"){
secondaryResults.thf += 1;
}
if ($(this).val() == "mageL"){
secondaryResults.mge += .98;
}
if ($(this).val() == "clericL"){
secondaryResults.cle += 1.03;
}
if ($(this).val() == "rangeL"){
secondaryResults.rng += .97;
}
if ($(this).val() == "druidL"){
secondaryResults.dru += 1.05;
}
})
});
$('#submit').on('click', function() {
$('input[name^= "answer"]:checked').each(function(){
if ($(this).val() == "monkM"){
secondaryResults.mnk += 1.31;
}
if ($(this).val() == "berserkerM"){
secondaryResults.ber += 1.29;
}
if ($(this).val() == "defenderM"){
secondaryResults.def += 1.3;
}
if ($(this).val() == "thiefM"){
secondaryResults.thf += 1.28;
}
if ($(this).val() == "mageM"){
secondaryResults.mge += 1.27;
}
if ($(this).val() == "cleric"){
secondaryResults.cle += 1.32;
}
if ($(this).val() == "rangeM"){
secondaryResults.rng += 1.33;
}
if ($(this).val() == "druidM"){
secondaryResults.dru += 1.26;
}
})
});
$('#submit').on('click', function() {
$('input[name^= "answer"]:checked').each(function(){
if ($(this).val() == "monkH"){
secondaryResults.mnk += 1.5;
}
if ($(this).val() == "berserkerH"){
secondaryResults.ber += 1.51;
}
if ($(this).val() == "defenderH"){
secondaryResults.def += 1.52 ;
}
if ($(this).val() == "thiefH"){
secondaryResults.thf += 1.49;
}
if ($(this).val() == "mageH"){
secondaryResults.mge += 1.48;
}
if ($(this).val() == "clericH"){
secondaryResults.cle += 1.47;
}
if ($(this).val() == "rangeH"){
secondaryResults.rng += 1.53;
}
if ($(this).val() == "druidH"){
secondaryResults.dru += 1.51;
}
})
});
$('#submit').on('click', function() {
$('input[name^= "answer"]:checked').each(function(){
if ($(this).val() == "monkPL"){
primaryResults.mnk += .96;
}
if ($(this).val() == "berserkerPL"){
primaryResults.ber += .97;
}
if ($(this).val() == "defenderPL"){
primaryResults.def += .98;
}
if ($(this).val() == "thiefPL"){
primaryResults.thf += .99;
}
if ($(this).val() == "magePL"){
primaryResults.mge += 1;
}
if ($(this).val() == "clericPL"){
primaryResults.cle += 1.01;
}
if ($(this).val() == "rangePL"){
primaryResults.rng += 1.02;
}
if ($(this).val() == "druidPL"){
primaryResults.dru += 1.03;
}
})
});
$('#submit').on('click', function() {
$('input[name^= "answer"]:checked').each(function(){
if ($(this).val() == "monkP"){
primaryResults.mnk += 1.3;
}
if ($(this).val() == "berserkerPM"){
primaryResults.ber += 1.26;
}
if ($(this).val() == "defenderPM"){
primaryResults.def += 1.27;
}
if ($(this).val() == "thiefPM"){
primaryResults.thf += 1.28;
}
if ($(this).val() == "magePM"){
primaryResults.mge += 1.29;
}
if ($(this).val() == "clericPM"){
primaryResults.cle += 1.31;
}
if ($(this).val() == "rangePM"){
primaryResults.rng += 1.32;
}
if ($(this).val() == "druidPM"){
primaryResults.dru += 1.33;
}
})
});
$('#submit').on('click', function() {
$('input[name^= "answer"]:checked').each(function(){
if ($(this).val() == "monkPH"){
primaryResults.mnk += 1.46;
}
if ($(this).val() == "berserkerPH"){
primaryResults.ber += 1.47;
}
if ($(this).val() == "defenderPH"){
primaryResults.def += 1.48 ;
}
if ($(this).val() == "thiefPH"){
secondaryResults.thf += 1.49;
}
if ($(this).val() == "magePH"){
primaryResults.mge += 1.5;
}
if ($(this).val() == "clericPH"){
primaryResults.cle += 1.51;
}
if ($(this).val() == "rangePH"){
primaryResults.rng += 1.52;
}
if ($(this).val() == "druidPH"){
primaryResults.dru += 1.536172;
}
$("#submit").css('display','none');
})
});
});
Screen cap of results
If I understood you, this is what you need:
let primaryResults = {
def: 0, ber: 5, mnk: 99999,
rng: 0, cle: 1, thf: 1,
mge: 0, dru: 1,
};
let secondaryResults = {
def: 1, ber: 0, mnk: 0,
rng: 1, cle: 33333333, thf: 0,
mge: 1, dru: 0,
};
let pH = 'def', sH = 'def';
let highestPrimary, highestSecondary;
Object.keys(primaryResults).map(key => {
if(primaryResults[key] > primaryResults[pH]) {
pH = key;
}
if(secondaryResults[key] > secondaryResults[sH]) {
sH = key;
}
});
highestPrimary = primaryResults[pH];
highestSecondary = secondaryResults[sH];
pH - key in primaryResults with the highest value
sH - key in resultsResults with the highest value
highestPrimary - the highest value in primaryResults
highestSecondary - the highest value in secondaryResults
Since i needed to have some variables of my programs available in all the pages, i decided to use cookies (js-cookie).
if ((Cookies.get('j') == null) || (Cookies.get('j') == 0)) {
Cookies.set('j', 0);
var j = parseInt(Cookies.get('j'));
}
Cookies.set('imuno');
var imuno = Cookies.get('imuno');
Cookies.set('imdue');
var imdue = Cookies.get('imdue');
Then i wrote two functions:
function check1(){
if ((src1 == "") || (src1 == "undefined")) {
alert("Selezionare un'immagine.");
}
else {
controllo();
}
}
and
function check2(){
if ((src2 == "") || (src2 == "undefined")) {
alert("Selezionare un'immagine.");
}
else {
controllo();
}
}
As you can see, they're two check functions that retrieve another function (controllo()) which works like that:
function controllo() {
if (j == 0) {
alert(j);
imuno = src1;
Cookies.set('imuno', src1);
alert(imuno);
location.href = "schienale.html";
j++;
Cookies.set('j', 1);
}
else if (j == 1){
alert(j);
imdue = src2;
Cookies.set('imdue', src2);
alert(imuno,imdue);
location.href = "riep.html";
j++;
Cookies.set('j', 2);
}}
All this code is written in my external .JS file. Now the funcion check1() works perfectly, but when the check2() start running the program doesn't work anymore, as if the cookie j doesn't mantain its value. How can i solve? Thanks all!
In this javascript code I try to solve a quadratic equation, I've been working on it for an hour and this should tell me the value of a, b and c where y is a(x^2). I'm a relative javascript beginner and would love some help. Why are the values of a, b and c not numbers? The variable names are in italian, in english and in something else(Not even I know what), but I commented what they are. That's one of my bad traits as a student that usually works alone, sorry if it's not easy to understand.
<script type="text/javascript">
var equa=prompt("Scrivi l'equazione senza spazi usando x come incognita e y come x^2");
var a = 0.0; b = 0.0; c = 0.0;//ax2+bx+c
var prima = true; //before or after equal?
var ope = 1;//1add 2sub 3mul 4div
var lasto = 0.0;//last number, used for div and mul
var lastos = 3; //1a2b3c
var errore=0;//is something messed up?
for(var i = 0; i < equa.length;i=i){
if(equa.charAt(i)=='='){
prima = false;
i++;
}else if(equa.charAt(i)=='+'){
ope=1;
i++;
}else if(equa.charAt(i)=='-'){
ope=2;
i++;
}else if(equa.charAt(i)=='*'){
ope=3;
i++;
}else if(equa.charAt(i)=='/'){
ope=4;
i++;
}else{
var nume = "";//Current number in string form
while(i<equa.length && equa.charAt(i)>'0' && equa.charAt(i)<'9'){
nume+=equa.charAt(i);
i++;
}
var lasnum = 0.0;//current number in float form
var lasval = 3; //1a2b3c
if(equa.charAt(i) == 'x'){
lasnum=parseFloat(nume);
lasval = 2;
}else if(equa.charAt(i) == 'y'){
lasnum=parseFloat(nume);
lasval = 1;
}else{
lasnum = parseFloat(nume);
lasval=3;
}
i++;
if( (ope == 1 || ope == 2) && !(equa.charAt(i) =='*' || equa.charAt(i) == '/')){
if(lasval == 1){
if(prima) a+=lasnum;
else a-=lasnum;
}
else if(lasval == 2){
if(prima) b+=lasnum;
else b-=lasnum;
}
else {
if(prima) c+=lasnum;
else c-=lasnum;
}
}else if( (ope==1 || ope == 2) && (equa.charAt(i) =='*' || equa.charAt(i) == '/')){
//zitto e fermo
lasto=lasnum;
lastos=lasval;
}else if( (ope==3||ope == 4)){
if(ope==3){
if(lastos==3){
lasnum*=lasto;
}
if(lastos == 2){
if(lastval==3){
lasnum*=lasto;
lastval=2;
}
if(lastval==2){
lasnum*=lasto;
lastval=1;
}
if(lastval==1){
errore=1;
}
}
if(lastos == 1){
if(lastval == 3){
lasnum*=lasto;
lastval=1;
}else{
errore=1;
}
}
}
if(ope == 4){
if(lastos == 1){
if(lastval==3){
lasnum/=lasto;
lastval=1;
}
if(lastval==2){
lasnum/=lasto;
lastval=2;
}
if(lastval==1){
lasnum/=lasto;
lastval=3;
}
}
if(lastos == 2){
if(lastval==1){
errore=1;
}
if(lastval==2){
lasnum/=lasto;
lastval=3;
}
if(lastval==3){
lasnum/=lasto;
lastval=2;
}
}
if(lastos == 3){
if(lastval==3){
lasnum/=lasto;
}else{
errore=1;
}
}
}
if(equa.charAt(i) =='*' || equa.charAt(i) == '/'){
lasto=lasnum;
lasto=lasval;
}else{
if(lasval == 1){
if(prima) a+=lasnum;
else a-=lasnum;
}
else if(lasval == 2){
if(prima) b+=lasnum;
else b-=lasnum;
}
else {
if(prima) c+=lasnum;
else c-=lasnum;
}
lasto=0;
lastos=3;
}
}
}
}
if(errore==0){
alert("a ="+a+" b="+b+" c="+c);
}else{
alert("AOOOOOOo");
}
</script>
Since the expected input should be in the format "15y+3x+5=20" for example, then this is a simple regular expression:
var equa = prompt("Scrivi l'equazione senza spazi usando x come incognita e y come x^2");
var regex = /^([0-9.]+)y\+([0-9.]+)x\+([0-9.]+)=([0-9.]+)$/;
var matches = regex.exec(equa);
if (matches) {
var a = parseFloat(matches[1]);
var b = parseFloat(matches[2]);
var c = parseFloat(matches[3]) - parseFloat(matches[4]);
var discriminant = b*b - 4*a*c;
if (discriminant < 0) {
alert('No real solutions');
}
else {
var root = Math.sqrt(discriminant);
alert('Root: ' + ((-b + root)/(2*a)) + ', ' + ((-b - root)/(2*a)));
}
}
else {
alert("AOOOOOOo");
}
I am trying to make a form validate where there are radio buttons and textarea. I want nothing to be left empty i.e the form should be completely filled. I have done the radio buttons part of validation where if a user does not select a radio button he will get an error for that particular question. you can see the code here for detailed code.
Please help me out. I am not getting error for textarea.
Just add another check for textarea
function RadioValidator() {
var ShowAlert = '';
var AllFormElements = window.document.getElementById("FormID").elements;
for (i = 0; i < AllFormElements.length; i++) {
var name = AllFormElements[i].name;
if (AllFormElements[i].type == 'radio') {
....
} else if (AllFormElements[i].type == 'textarea') {
if (AllFormElements[i].value == '') {
ShowAlert += name + ' textarea must be filled\n';
}
}
}
if (ShowAlert !== '') {
alert(ShowAlert);
return false;
} else {
return true;
}
}
you didn't write any validation for 'textarea' block. I have updated it with one textarea... add rest validations.
function RadioValidator()
{
var ShowAlert = '';
var AllFormElements = window.document.getElementById("FormID").elements;
for (i = 0; i < AllFormElements.length; i++)
{
if (AllFormElements[i].type == 'radio')
{
var ThisRadio = AllFormElements[i].name;
var ThisChecked = 'No';
var AllRadioOptions = document.getElementsByName(ThisRadio);
var problem_desc = document.getElementById("problem_desc");
for (x = 0; x < AllRadioOptions.length; x++)
{
if (AllRadioOptions[x].checked && ThisChecked === 'No' && problem_desc.value === "")
{
ThisChecked = 'Yes';
break;
}
}
var AlreadySearched = ShowAlert.indexOf(ThisRadio);
if (ThisChecked == 'No' && AlreadySearched == -1 && problem_desc.value === "")
{
ShowAlert = ShowAlert + ThisRadio + ' option must be selected\n';
}
}else if(AllFormElements[i].type =='textarea')
{
// add your rest of text area validations here
var problem_desc_1 = document.getElementById("problem_desc");
if(problem_desc_1.value === "")
{
ShowAlert = ShowAlert + '"Services (Please Specify)" can not be blank. \n';
}
}
}
if (ShowAlert !== '')
{
alert(ShowAlert);
return false;
}
else
{
return true;
}
}
You need to add a check for textarea as well
In your javascript check you have only added a condition for type radio.
check for textarea type as well and add error if the value is blank.