Use jQuery UI dialog yes no

For this example, I’m using jQuery version 3.2.1. The javascript method popupConfirm() can be called on the click of a button event or onchange event of a drop-down. The no-close class is to remove the x button from top-right of the dialog box.

< link href="../Scripts/jquery-ui.css" rel="stylesheet" />
< script src="../Scripts/jquery.js"></script>
< script src="../Scripts/jquery-ui.js"></script>
< style>
	.no-close .ui-dialog-titlebar-close{
		display: none;
	}
< /style>
<script language="JavaScript">   
    $(document).ready(function () {
        $("#dialog").dialog({
            autoOpen: false,
            modal: true,
            width: 400
        });
    });

    function popupConfirm() {
        $("#dialog").dialog({
			buttons: {
				"Yes": function () {
					$("#message").text('You clicked Yes');
					$(this).dialog("close");
				},
				"No": function () {
					$("#message").text('You clicked No');
					$(this).dialog("close");
				}
			},
			dialogClass: "no-close"
		});

		$("#dialog").dialog("open");
    }
</script>

Use the following html for the dialog and message as below.

< div id="dialog" title="Confirmation Required" >
  Are you sure?
< /div >
< div id="message" style="color: red;" >

< /div >

Use onchange method of a drop-down e.g.

< select name = 'types' size='1' onchange='popupConfirm();'> < /select> 

Show multiline text svg circle

For creating a circle using svg, you can follow this post. Then add the below code within the svg view box.

Normally you can use text tag to show some text in a svg component. But in order to show multiline text, we need to use HTML inside foreignObject tag as shown below:

< foreignObject id="content" x="20" y="25" width="100" height="100" >
                    < div >
                        < p id="txt1" style="font-size: 12px;">Text 1< /p >
                        < p id="txt2" style="font-size: 12px;">Text 2< /p >
                    < /div >
                < /foreignObject >

The x, y values should be set according to the svg view box. You can also use normal Javascript to modify the text using innerText property as below:

document.getElementById("txt1").innerText = "New Text 1";

Circular Progress bar svg javascript

In this post, I’ll give the code to create a Circular progress bar which I tried with a Start button and it resets every time you click on the start button and ticks every second for 60 seconds. The start button is shown using media control html code. The start button will re-appear once timer is reset.

If you’re using Asp.net Core MVC template, I’ve put the below code in index.cshtml file.

The HTML is as below:

< div >
            < svg class="progress-ring"
                 width="120"
                 height="120" >
                < circle class="progress-ring__circle"
                        stroke="orange"
                        stroke-width="4"
                        fill="transparent"
                        r="58"
                        cx="60"
                        cy="60" / >
                < text id="play" x="40" y="70" onclick="startTimer()" >▶< /text >
            < /svg >
< /div >

Css is as follows in the site.css file:

.progress-ring {
}

.progress-ring__circle {
    transition: 0.35s stroke-dashoffset;
    transform-origin: 50% 50%;
}

#play {
    cursor: pointer;
    font-size: xx-large;
}

The below Javascript code is going to modify the svg stroke-dashoffset attribute as below in the site.js file:

var i = 0;
var interval;
var circle = document.querySelector('circle');
var radius = circle.r.baseVal.value;
var circumference = radius * 2 * Math.PI;
console.log('radius', radius);
console.log('circumference', circumference);
circle.style.strokeDasharray = `${circumference} ${circumference}`;
circle.style.strokeDashoffset = `${circumference}`;

function setProgress(percent) {
    const offset = circumference - percent / 100 * circumference;
    circle.style.strokeDashoffset = offset;
}

function startTimer() {
    console.log('circumference', circumference);
    circle.style.strokeDashoffset = `${circumference}`;
    document.getElementById("play").textContent = "ok";
    interval = setInterval(increment, 1000);
}

function increment() {
    i = i % 360 + 1;
    var perc = (i / 60) * 100;
    console.log(i);
    if (i === 60) {
        clearInterval(interval);
        document.getElementById("play").textContent = "\u25B6";
        i = 0;
    }
    setProgress(perc);
}

The stroke-dashoffset value is reduced every time to increase the progress with stroke-dasharray. You can play around with the radius to increase the circle size.

Create html div as circle using HTML and css

Create the following div on your HTML page as below:

< div id=”circularDiv” class=”circluarDiv” >< /div >

Add the following css in your html file or common css file that you’re importing:

.circluarDiv {
     width: 100px;
     height: 100px;
     background-color: whitesmoke;
     border: 1px solid black;
     border-radius: 50%;
 }

Please note that the width and height should be equal for the div. Keep the border and background colours distinct to easily recognize the element.

The border-radius is giving rounded corners to the Div.

Send email with classic asp

Below is an example function used in my classic asp code to send e-mail with Attachments. The e-mail is written in HTML format and attachments picked up from the physical path on the Server where the Application is hosted on IIS.

I’m using a hard-coded path in the sample below for the Attachment example. You can create a dynamic string by fetching the path from the DB.

I’m using CDOSYS mail provider object below to send e-mail.

Function GenerateEmailCEF(senderemail, recipient)
MailProvider = "CDOSYS"
EmailFmt = 0 'For HTML, 1 is for Plain Text ' SMTP Server Config
Dim rsSMTPSendUsing, rsSMTPServer, rsSMTPServerPort, rsSMTPSendUsername, rsSMTPSendPassword, rsSMTPUseSSL Dim SMTPSendUsing, SMTPServer, SMTPServerPort, SMTPSendUsername, SMTPSendPassword, SMTPUseSSL

SMTPSendUsing = "1"
SMTPServer = "smtp.xx.xx" 'Change as per your configuration.
SMTPServerPort = "25"
SMTPSendUsername = ""
SMTPSendPassword = ""
SMTPUseSSL = "false"

if MailProvider = "CDONTS" then set objMail=CreateObject("CDONTS.NewMail")

if MailProvider = "CDOSYS" then set objMail =CreateObject("CDO.Message")

objMail.From = senderemail
objMail.To = recipient
objMail.Subject = "Test Subject"

if MailProvider = "CDONTS" then objMail.MailFormat = EmailFmt
if MailProvider = "CDONTS" then objMail.BodyFormat = EmailFmt

'Created only HTML format
emailbod = "<html?<HEAD?<TITLE?</TITLE?</HEAD?<BODY?" 'Fix this
emailbod = emailbod & "<BR?Mail Body." 'Fix this

'Add attachments to mail.
newfn = "c:\Data\myfile.pdf" 'Path on the Server.

if MailProvider = "CDONTS" then execute ("objMail.AttachFile(" & newfn & ")")

if MailProvider = "CDOSYS" then execute ("objMail.AddAttachment(" & newfn & ")")

if MailProvider = "CDONTS" then objMail.Body = emailbod
if MailProvider = "CDOSYS" then objMail.HTMLBody = emailbod

objMail.BodyPart.Charset = "UTF-8"
objMail.HTMLBodyPart.Charset = "UTF-8"

if MailProvider = "CDOSYS" then
objmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = SMTPSendUsing
objmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = SMTPServer
objmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = SMTPServerPort
objmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = SMTPUseSSL

if SMTPSendusername <> "" then
objmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusername") = SMTPSendusername
objmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendpassword") = SMTPSendPassword
objmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
end if

objmail.Configuration.Fields.Update
end if

objMail.Send
set objMail=Nothing
End Function

Download word file without Protected View .Net ReactJS

I have an Intranet Application where a .docm template downloaded from a ReactJS UI as a blob is opening in Protected View on the users’ machines. This is happening when downloading in browsers other than IE or Edge browser in IE mode.

When you download the document from Chrome or other browsers, MS Word is considering it as an Internet Application. Hence, the checkbox for Protected View is applying these changes and downloading it in Protected View.

Enable Protected View For Files Originating From The Internet. This setting controls documents opened from a website.

The code to download this as a blob is in ReactJS is available here.

However, if you generate the .docm file on the Server where the API is located and put it in a location on the Server itself. Create a Virtual Directory in IIS to make the document downloadable as http. So just return the hyperlink at the Client-side Javascript. You can receive this hyperlink and assign to anchor link clicking it through code.

var downloadUrl = response.data.Path;
        const link = document.createElement("a");
        link.id = "DownloadLink";
        link.href = downloadUrl;
        link.setAttribute("download", "filename");
        document.body.appendChild(link);
        link.click();
        document.getElementById("DownloadLink").outerHTML = "";

This will prevent it from opening in Protected View.

Also, if your word file has Macros, read-only fields become editable when you click on “Enable Editing” when you open the document in Protected View until you enable the Macros.

Change highlight color Autocomplete Material UI ReactJS

Create the below styles in your ReactJS component:

const styles = (theme) => ({
  ////....
  option: {
    // Hover
 with light-grey
    '&[data-focus="true"]': {
      backgroundColor: '#F8F8F8',
      borderColor: 'transparent',
    },
    // Selected
 has dark-grey
    '&[aria-selected="true"]': {
      backgroundColor: theme.palette.grey.A200,
      borderColor: 'transparent',
    },
  },
});

You can choose the colors based on your preference on selected and for mouse-over for backgroundColor property.

Add the following property in your AutoComplete component

classes={{
	  option: classes.option
	}}

as shown below:

<Autocomplete
	id="combo-box-1"
	options={myvalues}
	getOptionLabel={(option) => option.value}
	size="small"
	className={classes.formControlAutopopulate}
	classes={{
	  option: classes.option
	}}
	value={myvalues.find((x) => x.id === this.state.ID)}
	disabled={this.props.isLocked}
	onChange={this.handleSelected}
	renderInput={(params) => (
	  <TextField
		{...params}
		variant="outlined"
		placeholder="Please Select Value"
		fullWidth
	  />
	)}
/>

Set focus on tabbing ReactJS

I was working on Material-UI ExpansionPanel and had come across a task where I had to set focus on tabbing through them using keyboard. So when you press space on Focus, the Panel would open/close.

The ExpansionPanel sample implementation would be as below inside render:

return(
	<div>
	  <div className={classes.root}>
		{this.state.panelTypes.map((item) => (
		  <ExpansionPanel key={item.userType} expanded={this.state.expanded === item.userType} onChange={this.handleChange(item.userType)}>
			<ExpansionPanelSummary
			  expandIcon={<ExpandMoreIcon />}
			  aria-controls="panel1bh-content"
			  id="panel1bh-header"
			  style={{backgroundColor: "#e6e6e6", border: '1px solid silver'}}
			  className={classes.heading}
			>
			  <Typography className={classes.heading}>Heading</Typography>
			</ExpansionPanelSummary>
			<ExpansionPanelDetails>
			... display data here...
			</ExpansionPanelDetails>
		  </ExpansionPanel>
		))}
	  </div>
	</div>
  );

The above code is mapping through an array of PanelTypes for creating multiple ExpansionPanels.

The class would require the pseudo-class :focus to be used for tabbing through the Expansion Panel heading:

const styles = (theme) => ({
	//There might be other classes here..
  heading: {
    fontSize: theme.typography.pxToRem(15),
    flexBasis: '33.33%',
    flexShrink: 0,
    fontFamily: "Verdana,Arial,sans-serif",
    '&:focus': {
      outline: "-webkit-focus-ring-color auto 1px"
    }
  }
});

Similarly, other pseudo-classes can be used inside the styles e.g. ::after, ::before etc. as per their own usage.

Material-table example ReactJS

There are a lot of scenarios in Material-table that you might have difficulty in understanding from the documentation or may be scattered on different forums. I’ll try to cover up the scenarios which I faced while implementing a table in my Project with Actions like Add/Edit/Delete. Another scenario is to make it read-only i.e. remove all the Action buttons.

This is the sample courses React App over which I’ll develop further using Material-Table. You can get the code from the Github Project here. To get started, you’ll need the following packages:

npm i @material-ui/core
npm i @material-ui/icons
npm i @material-ui/lab
npm i material-table
npm i axios

The actions are managed through uncontrolled fields i.e. without managing through state directly. The API calls are as per my example and URL placeholder requires to be updated as per your API host name.

The columns and icons are set in the state. autoFocus property is set to the first TextField for edit mode.

The options prop which I’ve used has Paging, sorting and dragging of columns disabled. Sorting and draggable can simply be set to true and used.

To make the table read-only, the editable prop of Material Table can be set to null conditionally. I’ve used isReadOnly boolean to add the condition, you can have your own state here.

render() {
    const { classes } = this.props;
    return (
      <Fragment>
         <div
            id={this.props.id}
          >
            <MaterialTable
              components={{
                EditRow: (props) => {
                  return (
                    <MTableEditRow
                      {...props}
                      onEditingCanceled={(mode, rowData) => {
                        this.canceledClicked();
                        props.onEditingCanceled(mode);
                      }}
                    />
                  );
                },
              }}
              title=""
              columns={this.state.columns}
              data={this.state.StudentsEnrolled}
              icons={this.state.tableIcons}
              isLoading={this.state.showLoading}
              style={{
                border: "2px solid gray",
                maxWidth: "1450px",
                overflow: "scroll",
                marginTop: "10px",
                marginLeft: "20px",
              }}
              editable={
                isReadOnly
                ? null
                : 
                {
                onRowAdd: (newData) =>
                  new Promise((resolve, reject) => {
                    newData.studentName =
                      studentName_GRC === null ? "" : studentName_GRC;
                    
                    newData.grade = grade_GR === null ? "" : grade_GR;

                    newData.courseName = courseName_GR === null ? "" : courseName_GR;

                    newData.comments = comments_GR === null ? "" : comments_GR;

                    var errorMsg = " ";

                    if (newData.studentName === "") {
                      errorMsg = "Please insert Student Name.";
                    }
                    if (newData.grade === "") {
                      errorMsg = errorMsg + "\nPlease insert grade.";
                    }
                    if (newData.courseName === "") {
                      errorMsg = errorMsg + "\nPlease insert course Name.";
                    }

                    if (errorMsg !== " ") {
                      reject();
                      alert(errorMsg);
                    } else if (this.state.countGrid >= GridDataLimit) {
                      reject();
                      alert(
                        "You cannot add more than " +
                          GridDataLimit +
                          " Students to the list."
                      );
                    } else {
                      this.setState({ showLoading: true });
                      this.postStudentsEnrolledData(newData);
                      resolve();
                    }
                    // }, 600);
                  }),
                onRowUpdate: (newData, oldData) =>
                  new Promise((resolve, reject) => {
                    // setTimeout(() => {
                    //resolve();

                    if (oldData) {
                      newData.studentName =
                        studentName_GRC === null
                          ? oldData.studentName
                          : studentName_GRC === ""
                          ? ""
                          : studentName_GRC;

                      newData.grade =
                        grade_GR === null
                          ? oldData.grade
                          : grade_GR === ""
                          ? ""
                          : grade_GR;

                      newData.courseName =
                        courseName_GR === null
                          ? oldData.courseName
                          : courseName_GR === ""
                          ? ""
                          : courseName_GR;

                      newData.comments =
                        comments_GR === null
                          ? oldData.comments
                          : comments_GR === ""
                          ? ""
                          : comments_GR;

                      var errorMsg = " ";
                      if (newData.studentName === "") {
                        errorMsg = "Please insert Student Name.";
                      }
                      if (newData.grade === "") {
                        errorMsg = errorMsg + "\nPlease insert grade.";
                      }
                      if (newData.courseName === "") {
                        errorMsg = errorMsg + "\nPlease insert course Name.";
                      }
                      if (errorMsg !== " ") {
                        reject();
                        alert(errorMsg);
                      } else {
                        this.setState({ showLoading: true });
                        this.postStudentsEnrolledData(newData);
                        resolve();
                      }
                    }
                    // }, 600);
                  }),
                onRowDelete: (oldData) =>
                  new Promise((resolve) => {
                    // setTimeout(() => {
                    this.setState({ showLoading: true });
                    this.deleteStudentsEnrolledData(oldData);
                    resolve();
                    // }, 600);
                  }),
              }}
              options={{
                paging: false,
                sorting: false,
                draggable: false,
                addRowcourseName:"first",
                rowStyle: { backgroundColor: "#fff" },
              }}
            />
          </div>
      </Fragment>
    );
  }

The isLoading prop manages the hide/show of loader when an action is performed.

There is one more scenario where clicking outside the + icon, doesn’t trigger the onAddRowClick event. This is handled in componentDidMount method.

Render elements dynamically using map Reactjs

Here I’m using a component that needs to render multiple ExpansionPanel Material UI components based on data fetched in an array. The map is using Arrow function with () for an implicit return.

Below is the sample code for the Component:

import React, { Component } from "react";
import Header from "./Header";
import { withStyles } from '@material-ui/core/styles';
import ExpansionPanel from '@material-ui/core/ExpansionPanel';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import Typography from '@material-ui/core/Typography';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import loadingImg from "../images/LoadingImg_EZ.gif";

const styles = (theme) => ({
  root: {
    width: '100%',
  },
  heading: {
    fontSize: theme.typography.pxToRem(15),
    flexBasis: '33.33%',
    flexShrink: 0,
    fontWeight: 'bold',
  },
  secondaryHeading: {
    fontSize: theme.typography.pxToRem(15),
    color: theme.palette.text.secondary,
  },
  OfflineText: {
    fontSize: "20px",
    color: "red",
  },
});

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      expanded: false,
      panelTypes: null,
      summary: null
    };
  }

  componentWillMount() {
    //get data here and set state.
  }

  handleChange = (panel) => (event, isExpanded) => {
    this.setState({ expanded: isExpanded? panel: false});
  };

  render() {
      const { classes } = this.props;
      
      return(
        <div>
        <Header />
        {this.state.panelTypes !=null ? (
        <>
          <h3 style={{fontSize: "15px", paddingLeft: "4px"}}>Summary</h3>
          <div className={classes.root}>
            {this.state.panelTypes.map((item) => (
              <ExpansionPanel expanded={this.state.expanded === item.types} onChange={this.handleChange(item.types)}>
                <ExpansionPanelSummary
                  expandIcon={<ExpandMoreIcon />}
                  aria-controls="panel1bh-content"
                  id="panel1bh-header"
                  style={{backgroundColor: "#e6e6e6"}}
                >
                  <Typography className={classes.heading}>{this.state.panelTypes !=null ? `${item.types} (Year ${item.year})`:''}</Typography>
                </ExpansionPanelSummary>
                <ExpansionPanelDetails>
                  <Typography>
                    Nulla facilisi. Phasellus sollicitudin nulla et quam mattis feugiat. Aliquam eget
                    maximus est, id dignissim quam.
                  </Typography>
                </ExpansionPanelDetails>
              </ExpansionPanel>
            ))}
          </div>
          </>) : (
          <div id="loading">
            <img id="loading-image" src={loadingImg} alt="Loading..." />
          </div>
        )}
        </div>
      );
  }

}

export default withStyles(styles, { withTheme: true })((MyComponent));
panelTypes will hold the array of items that will be used to create the same number of Expansion Panels using this.state.panelTypes.map() in the render method.