[CONTACT]

[ABOUT]

[POLICY]

git clone dmenu dmenu Log gph

Found at: gopher.r-36.net:70/scm/dmenu/commit/7817523a685f0dbba2e074a448099558a54b1b9c.gph

tinitial import - dmenu - Dmenu fork with xft fonts.

git clone git://r-36.net/dmenu

Log

Files

Refs

README

LICENSE

---

commit 7817523a685f0dbba2e074a448099558a54b1b9c

Author: arg@10ksloc.org

Date:   Fri,  4 Aug 2006 09:35:27 +0200
initial import
Diffstat:
  LICENSE                             |      21 +++++++++++++++++++++
  Makefile                            |      61 +++++++++++++++++++++++++++++++
  README                              |      48 +++++++++++++++++++++++++++++++
  config.arg.h                        |       9 +++++++++
  config.default.h                    |       9 +++++++++
  config.h                            |       9 +++++++++
  config.mk                           |      24 ++++++++++++++++++++++++
  dmenu.1                             |      68 +++++++++++++++++++++++++++++++
  dmenu.h                             |      58 ++++++++++++++++++++++++++++++
  draw.c                              |     171 +++++++++++++++++++++++++++++++
  main.c                              |     426 +++++++++++++++++++++++++++++++
  util.c                              |      68 +++++++++++++++++++++++++++++++
12 files changed, 972 insertions(+), 0 deletions(-)
---

diff --git a/LICENSE b/LICENSE

t@@ -0,0 +1,21 @@
+MIT/X Consortium License
+
+(C)opyright MMVI Anselm R. Garbe 
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.

diff --git a/Makefile b/Makefile

t@@ -0,0 +1,61 @@
+# dmenu - dynamic menu
+#   (C)opyright MMVI Anselm R. Garbe
+
+include config.mk
+
+SRC = draw.c main.c util.c
+OBJ = ${SRC:.c=.o}
+
+all: options dmenu
+        @echo finished
+
+options:
+        @echo dmenu build options:
+        @echo "CFLAGS   = ${CFLAGS}"
+        @echo "LDFLAGS  = ${LDFLAGS}"
+        @echo "CC       = ${CC}"
+
+.c.o:
+        @echo CC $<
+        @${CC} -c ${CFLAGS} $<
+
+${OBJ}: dmenu.h config.h
+
+config.h:
+        @echo creating $@ from config.default.h
+        @cp config.default.h $@
+
+dmenu: ${OBJ}
+        @echo LD $@
+        @${CC} -o $@ ${OBJ} ${LDFLAGS}
+
+clean:
+        @echo cleaning
+        @rm -f dmenu ${OBJ} dmenu-${VERSION}.tar.gz
+
+dist: clean
+        @echo creating dist tarball
+        @mkdir -p dmenu-${VERSION}
+        @cp -R LICENSE Makefile README config.mk \
+                dmenu.1 dmenu.h ${SRC} dmenu-${VERSION}
+        @tar -cf dmenu-${VERSION}.tar dmenu-${VERSION}
+        @gzip dmenu-${VERSION}.tar
+        @rm -rf dmenu-${VERSION}
+
+install: all
+        @echo installing executable file to ${DESTDIR}${PREFIX}/bin
+        @mkdir -p ${DESTDIR}${PREFIX}/bin
+        @cp -f dmenu ${DESTDIR}${PREFIX}/bin
+        @chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu
+        @echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
+        @mkdir -p ${DESTDIR}${MANPREFIX}/man1
+        @cp -f dmenu.1 ${DESTDIR}${MANPREFIX}/man1
+        @chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1
+
+uninstall:
+        @echo removing executable file from ${DESTDIR}${PREFIX}/bin
+        @rm -f ${DESTDIR}${PREFIX}/bin/dmenu
+        @echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
+        @rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1
+
+.PHONY: all options clean dist install uninstall

diff --git a/README b/README

t@@ -0,0 +1,48 @@
+dwm - dynamic window manager
+----------------------------
+dwm is an extremely fast, small, and dynamic X11 window manager.
+
+
+Requirements
+------------
+In order to build dwm you need the Xlib header files.
+
+
+Installation
+------------
+Edit config.mk to match your local setup (dwm is installed into
+the /usr/local namespace by default).
+
+Afterwards enter the following command to build and install dwm (if
+necessary as root):
+
+    make clean install
+
+
+Running dwm
+-----------
+Add the following line to your .xinitrc to start dwm using startx:
+
+    exec dwm
+
+In order to connect dwm to a specific display, make sure that
+the DISPLAY environment variable is set correctly, e.g.:
+
+    DISPLAY=foo.bar:1 exec dwm
+
+(This will start dwm on display :1 of the host foo.bar.)
+
+In order to display status info in the bar, you can do something
+like this in your .xinitrc:
+
+    while true
+    do
+        echo `date` `uptime | sed 's/.*://; s/,//g'`
+        sleep 1
+    done | dwm
+
+
+Configuration
+-------------
+The configuration of dwm is done by creating a custom config.h
+and (re)compiling the source code.

diff --git a/config.arg.h b/config.arg.h

t@@ -0,0 +1,9 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe 
+ * See LICENSE file for license details.
+ */
+
+#define FONT                        "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*"
+#define BGCOLOR                        "#0a2c2d"
+#define FGCOLOR                        "#ddeeee"
+#define BORDERCOLOR                "#176164"

diff --git a/config.default.h b/config.default.h

t@@ -0,0 +1,9 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe 
+ * See LICENSE file for license details.
+ */
+
+#define FONT                        "fixed"
+#define BGCOLOR                        "#666699"
+#define FGCOLOR                        "#eeeeee"
+#define BORDERCOLOR                "#9999CC"

diff --git a/config.h b/config.h

t@@ -0,0 +1,9 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe 
+ * See LICENSE file for license details.
+ */
+
+#define FONT                        "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*"
+#define BGCOLOR                        "#0a2c2d"
+#define FGCOLOR                        "#ddeeee"
+#define BORDERCOLOR                "#176164"

diff --git a/config.mk b/config.mk

t@@ -0,0 +1,24 @@
+# dwm version
+VERSION = 0.0
+
+# Customize below to fit your system
+
+# paths
+PREFIX = /usr/local
+MANPREFIX = ${PREFIX}/share/man
+
+X11INC = /usr/X11R6/include
+X11LIB = /usr/X11R6/lib
+
+# includes and libs
+INCS = -I/usr/lib -I${X11INC}
+LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
+
+# flags
+CFLAGS = -O3 ${INCS} -DVERSION=\"${VERSION}\"
+LDFLAGS = ${LIBS}
+#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
+#LDFLAGS = -g ${LIBS}
+
+# compiler
+CC = cc

diff --git a/dmenu.1 b/dmenu.1

t@@ -0,0 +1,68 @@
+.TH DMENU 1 d-0.0
+.SH NAME
+dmenu \- dynamic menu
+.SH SYNOPSIS
+.B dmenu
+.RB [ \-v ]
+.RB [ \-t
+.IR title ]
+.SH DESCRIPTION
+.SS Overview
+.B dmenu
+is a generic, highly customizable, and efficient menu for the X Window System,
+originally designed for
+.BR dwm (1).
+It supports arbitrary, user defined menu contents.
+.SS Options
+.TP
+.B \-v
+prints version information to stdout, then exits.
+.TP
+.BI \-t " title"
+displays
+.I title
+above the menu.
+.SS Usage
+.B dmenu
+reads a list of newline-separated items from stdin and creates a menu.
+When the user selects an item or enters any text and presses Enter, his choice
+is printed to stdout and
+.B dmenu
+terminates.
+.SS Keyboard Control
+.B dmenu
+is completely controlled by the keyboard.  The following keys are recognized:
+.TP 2
+Any printable character
+appends the character to the text in the input field. This works as a filter:
+only items containing this text will be displayed.
+.TP 2
+Left/Right (Control-p/Control-n)
+select the previous/next item.
+.TP 2
+Tab (Control-i)
+copy the selected item to the input field.
+.TP 2
+Enter (Control-j)
+confirm selection and quit (print the selected item to stdout).
+.TP 2
+Shift-Enter (Shift-Control-j)
+confirm selection and quit (print the text in the input field to stdout).
+.TP 2
+Escape (Control-[)
+quit without selecting an item.
+.TP 2
+Backspace (Control-h)
+remove enough characters from the input field to change its filtering effect.
+.TP 2
+Control-u
+remove all characters from the input field.
+.SS Exit codes
+.B dmenu
+returns
+.B 0
+if Enter is pressed on termination,
+.B 1
+if Escape is pressed.
+.SH SEE ALSO
+.BR dwm (1)

diff --git a/dmenu.h b/dmenu.h

t@@ -0,0 +1,58 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe 
+ * See LICENSE file for license details.
+ */
+
+#include "config.h"
+#include 
+#include 
+
+typedef struct Brush Brush;
+typedef struct DC DC;
+typedef struct Fnt Fnt;
+
+struct Fnt {
+        XFontStruct *xfont;
+        XFontSet set;
+        int ascent;
+        int descent;
+        int height;
+};
+
+struct DC { /* draw context */
+        int x, y, w, h;
+        unsigned long bg;
+        unsigned long fg;
+        unsigned long border;
+        Drawable drawable;
+        Fnt font;
+        GC gc;
+};
+
+struct Brush {
+        GC gc;
+        Drawable drawable;
+        int x, y, w, h;
+        Fnt font;
+        unsigned long bg;
+        unsigned long fg;
+        unsigned long border;
+};
+
+
+
+/* draw.c */
+extern void draw(Display *dpy, Brush *b, Bool border, const char *text);
+extern void loadcolors(Display *dpy, int screen, Brush *b,
+                const char *bg, const char *fg, const char *bo);
+extern void loadfont(Display *dpy, Fnt *font, const char *fontstr);
+extern unsigned int textnw(Fnt *font, char *text, unsigned int len);
+extern unsigned int textw(Fnt *font, char *text);
+extern unsigned int texth(Fnt *font);
+
+/* util.c */
+extern void *emalloc(unsigned int size);
+extern void *emallocz(unsigned int size);
+extern void eprint(const char *errstr, ...);
+extern char *estrdup(const char *str);
+extern void swap(void **p1, void **p2);

diff --git a/draw.c b/draw.c

t@@ -0,0 +1,171 @@
+/*
+ * (C)opyright MMIV-MMVI Anselm R. Garbe 
+ * See LICENSE file for license details.
+ */
+
+#include 
+#include 
+
+#include "dmenu.h"
+
+static void
+drawborder(Display *dpy, Brush *b)
+{
+        XPoint points[5];
+        XSetLineAttributes(dpy, b->gc, 1, LineSolid, CapButt, JoinMiter);
+        XSetForeground(dpy, b->gc, b->border);
+        points[0].x = b->x;
+        points[0].y = b->y;
+        points[1].x = b->w - 1;
+        points[1].y = 0;
+        points[2].x = 0;
+        points[2].y = b->h - 1;
+        points[3].x = -(b->w - 1);
+        points[3].y = 0;
+        points[4].x = 0;
+        points[4].y = -(b->h - 1);
+        XDrawLines(dpy, b->drawable, b->gc, points, 5, CoordModePrevious);
+}
+
+void
+draw(Display *dpy, Brush *b, Bool border, const char *text)
+{
+        unsigned int x, y, w, h, len;
+        static char buf[256];
+        XGCValues gcv;
+        XRectangle r = { b->x, b->y, b->w, b->h };
+
+        XSetForeground(dpy, b->gc, b->bg);
+        XFillRectangles(dpy, b->drawable, b->gc, &r, 1);
+
+        w = 0;
+        if(border)
+                drawborder(dpy, b);
+
+        if(!text)
+                return;
+
+        len = strlen(text);
+        if(len >= sizeof(buf))
+                len = sizeof(buf) - 1;
+        memcpy(buf, text, len);
+        buf[len] = 0;
+
+        h = b->font.ascent + b->font.descent;
+        y = b->y + (b->h / 2) - (h / 2) + b->font.ascent;
+        x = b->x + (h / 2);
+
+        /* shorten text if necessary */
+        while(len && (w = textnw(&b->font, buf, len)) > b->w - h)
+                buf[--len] = 0;
+
+        if(w > b->w)
+                return; /* too long */
+
+        gcv.foreground = b->fg;
+        gcv.background = b->bg;
+        if(b->font.set) {
+                XChangeGC(dpy, b->gc, GCForeground | GCBackground, &gcv);
+                XmbDrawImageString(dpy, b->drawable, b->font.set, b->gc,
+                                x, y, buf, len);
+        }
+        else {
+                gcv.font = b->font.xfont->fid;
+                XChangeGC(dpy, b->gc, GCForeground | GCBackground | GCFont, &gcv);
+                XDrawImageString(dpy, b->drawable, b->gc, x, y, buf, len);
+        }
+}
+
+static unsigned long
+xloadcolors(Display *dpy, Colormap cmap, const char *colstr)
+{
+        XColor color;
+        XAllocNamedColor(dpy, cmap, colstr, &color, &color);
+        return color.pixel;
+}
+
+void
+loadcolors(Display *dpy, int screen, Brush *b,
+                const char *bg, const char *fg, const char *border)
+{
+        Colormap cmap = DefaultColormap(dpy, screen);
+        b->bg = xloadcolors(dpy, cmap, bg);
+        b->fg = xloadcolors(dpy, cmap, fg);
+        b->border = xloadcolors(dpy, cmap, border);
+}
+
+unsigned int
+textnw(Fnt *font, char *text, unsigned int len)
+{
+        XRectangle r;
+        if(font->set) {
+                XmbTextExtents(font->set, text, len, NULL, &r);
+                return r.width;
+        }
+        return XTextWidth(font->xfont, text, len);
+}
+
+unsigned int
+textw(Fnt *font, char *text)
+{
+        return textnw(font, text, strlen(text));
+}
+
+unsigned int
+texth(Fnt *font)
+{
+        return font->height + 4;
+}
+
+void
+loadfont(Display *dpy, Fnt *font, const char *fontstr)
+{
+        char **missing, *def;
+        int n;
+
+        missing = NULL;
+        def = "?";
+        setlocale(LC_ALL, "");
+        if(font->set)
+                XFreeFontSet(dpy, font->set);
+        font->set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
+        if(missing) {
+                while(n--)
+                        fprintf(stderr, "missing fontset: %s\n", missing[n]);
+                XFreeStringList(missing);
+                if(font->set) {
+                        XFreeFontSet(dpy, font->set);
+                        font->set = NULL;
+                }
+        }
+        if(font->set) {
+                XFontSetExtents *font_extents;
+                XFontStruct **xfonts;
+                char **font_names;
+                unsigned int i;
+
+                font->ascent = font->descent = 0;
+                font_extents = XExtentsOfFontSet(font->set);
+                n = XFontsOfFontSet(font->set, &xfonts, &font_names);
+                for(i = 0, font->ascent = 0, font->descent = 0; i < n; i++) {
+                        if(font->ascent < (*xfonts)->ascent)
+                                font->ascent = (*xfonts)->ascent;
+                        if(font->descent < (*xfonts)->descent)
+                                font->descent = (*xfonts)->descent;
+                        xfonts++;
+                }
+        }
+        else {
+                if(font->xfont)
+                        XFreeFont(dpy, font->xfont);
+                font->xfont = NULL;
+                font->xfont = XLoadQueryFont(dpy, fontstr);
+                if (!font->xfont)
+                        font->xfont = XLoadQueryFont(dpy, "fixed");
+                if (!font->xfont)
+                        eprint("error, cannot load 'fixed' font\n");
+                font->ascent = font->xfont->ascent;
+                font->descent = font->xfont->descent;
+        }
+        font->height = font->ascent + font->descent;
+}

diff --git a/main.c b/main.c

t@@ -0,0 +1,426 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe 
+ * (C)opyright MMVI Sander van Dijk 
+ * See LICENSE file for license details.
+ */
+
+#include "dmenu.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+typedef struct Item Item;
+
+struct Item {
+        Item *next;                /* traverses all items */
+        Item *left, *right;        /* traverses items matching current search pattern */
+        char *text;
+};
+
+static Display *dpy;
+static Window root;
+static Window win;
+static Bool done = False;
+
+static Item *allitem = NULL;        /* first of all items */
+static Item *item = NULL;        /* first of pattern matching items */
+static Item *sel = NULL;
+static Item *nextoff = NULL;
+static Item *prevoff = NULL;
+static Item *curroff = NULL;
+
+static int screen, mx, my, mw, mh;
+static char *title = NULL;
+static char text[4096];
+static int ret = 0;
+static int nitem = 0;
+static unsigned int cmdw = 0;
+static unsigned int tw = 0;
+static unsigned int cw = 0;
+static const int seek = 30;                /* 30px */
+
+static Brush brush = {0};
+
+static void draw_menu();
+static void kpress(XKeyEvent * e);
+
+static char version[] = "dmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
+
+static void
+update_offsets()
+{
+        unsigned int tw, w = cmdw + 2 * seek;
+
+        if(!curroff)
+                return;
+
+        for(nextoff = curroff; nextoff; nextoff=nextoff->right) {
+                tw = textw(&brush.font, nextoff->text);
+                if(tw > mw / 3)
+                        tw = mw / 3;
+                w += tw + brush.font.height;
+                if(w > mw)
+                        break;
+        }
+
+        w = cmdw + 2 * seek;
+        for(prevoff = curroff; prevoff && prevoff->left; prevoff=prevoff->left) {
+                tw = textw(&brush.font, prevoff->left->text);
+                if(tw > mw / 3)
+                        tw = mw / 3;
+                w += tw + brush.font.height;
+                if(w > mw)
+                        break;
+        }
+}
+
+static void
+update_items(char *pattern)
+{
+        unsigned int plen = strlen(pattern);
+        Item *i, *j;
+
+        if(!pattern)
+                return;
+
+        if(!title || *pattern)
+                cmdw = cw;
+        else
+                cmdw = tw;
+
+        item = j = NULL;
+        nitem = 0;
+
+        for(i = allitem; i; i=i->next)
+                if(!plen || !strncmp(pattern, i->text, plen)) {
+                        if(!j)
+                                item = i;
+                        else
+                                j->right = i;
+                        i->left = j;
+                        i->right = NULL;
+                        j = i;
+                        nitem++;
+                }
+        for(i = allitem; i; i=i->next)
+                if(plen && strncmp(pattern, i->text, plen)
+                                && strstr(i->text, pattern)) {
+                        if(!j)
+                                item = i;
+                        else
+                                j->right = i;
+                        i->left = j;
+                        i->right = NULL;
+                        j = i;
+                        nitem++;
+                }
+
+        curroff = prevoff = nextoff = sel = item;
+
+        update_offsets();
+}
+
+/* creates brush structs for brush mode drawing */
+static void
+draw_menu()
+{
+        Item *i;
+
+        brush.x = 0;
+        brush.y = 0;
+        brush.w = mw;
+        brush.h = mh;
+        draw(dpy, &brush, False, 0);
+
+        /* print command */
+        if(!title || text[0]) {
+                cmdw = cw;
+                if(cmdw && item)
+                        brush.w = cmdw;
+                draw(dpy, &brush, False, text);
+        }
+        else {
+                cmdw = tw;
+                brush.w = cmdw;
+                draw(dpy, &brush, False, title);
+        }
+        brush.x += brush.w;
+
+        if(curroff) {
+                brush.w = seek;
+                draw(dpy, &brush, False, (curroff && curroff->left) ? "<" : 0);
+                brush.x += brush.w;
+
+                /* determine maximum items */
+                for(i = curroff; i != nextoff; i=i->right) {
+                        brush.border = False;
+                        brush.w = textw(&brush.font, i->text);
+                        if(brush.w > mw / 3)
+                                brush.w = mw / 3;
+                        brush.w += brush.font.height;
+                        if(sel == i) {
+                                swap((void **)&brush.fg, (void **)&brush.bg);
+                                draw(dpy, &brush, True, i->text);
+                                swap((void **)&brush.fg, (void **)&brush.bg);
+                        }
+                        else
+                                draw(dpy, &brush, False, i->text);
+                        brush.x += brush.w;
+                }
+
+                brush.x = mw - seek;
+                brush.w = seek;
+                draw(dpy, &brush, False, nextoff ? ">" : 0);
+        }
+        XCopyArea(dpy, brush.drawable, win, brush.gc, 0, 0, mw, mh, 0, 0);
+        XFlush(dpy);
+}
+
+static void
+kpress(XKeyEvent * e)
+{
+        KeySym ksym;
+        char buf[32];
+        int num, prev_nitem;
+        unsigned int i, len = strlen(text);
+
+        buf[0] = 0;
+        num = XLookupString(e, buf, sizeof(buf), &ksym, 0);
+
+        if(IsFunctionKey(ksym) || IsKeypadKey(ksym)
+                        || IsMiscFunctionKey(ksym) || IsPFKey(ksym)
+                        || IsPrivateKeypadKey(ksym))
+                return;
+
+        /* first check if a control mask is omitted */
+        if(e->state & ControlMask) {
+                switch (ksym) {
+                default:        /* ignore other control sequences */
+                        return;
+                        break;
+                case XK_h:
+                        ksym = XK_BackSpace;
+                        break;
+                case XK_U:
+                case XK_u:
+                        text[0] = 0;
+                        update_items(text);
+                        draw_menu();
+                        return;
+                        break;
+                case XK_bracketleft:
+                        ksym = XK_Escape;
+                        break;
+                }
+        }
+        switch(ksym) {
+        case XK_Left:
+                if(!(sel && sel->left))
+                        return;
+                sel=sel->left;
+                if(sel->right == curroff) {
+                        curroff = prevoff;
+                        update_offsets();
+                }
+                break;
+        case XK_Tab:
+                if(!sel)
+                        return;
+                strncpy(text, sel->text, sizeof(text));
+                update_items(text);
+                break;
+        case XK_Right:
+                if(!(sel && sel->right))
+                        return;
+                sel=sel->right;
+                if(sel == nextoff) {
+                        curroff = nextoff;
+                        update_offsets();
+                }
+                break;
+        case XK_Return:
+                if(e->state & ShiftMask) {
+                        if(text)
+                                fprintf(stdout, "%s", text);
+                }
+                else if(sel)
+                        fprintf(stdout, "%s", sel->text);
+                else if(text)
+                        fprintf(stdout, "%s", text);
+                fflush(stdout);
+                done = True;
+                break;
+        case XK_Escape:
+                ret = 1;
+                done = True;
+                break;
+        case XK_BackSpace:
+                if((i = len)) {
+                        prev_nitem = nitem;
+                        do {
+                                text[--i] = 0;
+                                update_items(text);
+                        } while(i && nitem && prev_nitem == nitem);
+                        update_items(text);
+                }
+                break;
+        default:
+                if(num && !iscntrl((int) buf[0])) {
+                        buf[num] = 0;
+                        if(len > 0)
+                                strncat(text, buf, sizeof(text));
+                        else
+                                strncpy(text, buf, sizeof(text));
+                        update_items(text);
+                }
+        }
+        draw_menu();
+}
+
+static char *
+read_allitems()
+{
+        static char *maxname = NULL;
+        char *p, buf[1024];
+        unsigned int len = 0, max = 0;
+        Item *i, *new;
+
+        i = 0;
+        while(fgets(buf, sizeof(buf), stdin)) {
+                len = strlen(buf);
+                if (buf[len - 1] == '\n')
+                        buf[len - 1] = 0;
+                p = estrdup(buf);
+                if(max < len) {
+                        maxname = p;
+                        max = len;
+                }
+
+                new = emalloc(sizeof(Item));
+                new->next = new->left = new->right = NULL;
+                new->text = p;
+                if(!i)
+                        allitem = new;
+                else
+                        i->next = new;
+                i = new;
+        }
+
+        return maxname;
+}
+
+int
+main(int argc, char *argv[])
+{
+        int i;
+        XSetWindowAttributes wa;
+        char *maxname;
+        XEvent ev;
+
+        /* command line args */
+        for(i = 1; i < argc; i++) {
+                if (argv[i][0] == '-')
+                        switch (argv[i][1]) {
+                        case 'v':
+                                fprintf(stdout, "%s", version);
+                                exit(0);
+                                break;
+                        case 't':
+                                if(++i < argc) {
+                                        title = argv[i];
+                                        break;
+                                }
+                        default:
+                                eprint("usage: dmenu [-v] [-t ]\n");</pre>
<pre>+                                break;</pre>
<pre>+                        }</pre>
<pre>+                else</pre>
<pre>+                        eprint("usage: dmenu [-v] [-t <title>]\n");</pre>
<pre>+        }</pre>
<pre>+</pre>
<pre>+        dpy = XOpenDisplay(0);</pre>
<pre>+        if(!dpy)</pre>
<pre>+                eprint("dmenu: cannot open dpy\n");</pre>
<pre>+        screen = DefaultScreen(dpy);</pre>
<pre>+        root = RootWindow(dpy, screen);</pre>
<pre>+</pre>
<pre>+        maxname = read_allitems();</pre>
<pre>+</pre>
<pre>+        /* grab as early as possible, but after reading all items!!! */</pre>
<pre>+        while(XGrabKeyboard(dpy, root, True, GrabModeAsync,</pre>
<pre>+                         GrabModeAsync, CurrentTime) != GrabSuccess)</pre>
<pre>+                usleep(1000);</pre>
<pre>+</pre>
<pre>+        /* style */</pre>
<pre>+        loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR);</pre>
<pre>+        loadfont(dpy, &brush.font, FONT);</pre>
<pre>+</pre>
<pre>+        wa.override_redirect = 1;</pre>
<pre>+        wa.background_pixmap = ParentRelative;</pre>
<pre>+        wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask;</pre>
<pre>+</pre>
<pre>+        mx = my = 0;</pre>
<pre>+        mw = DisplayWidth(dpy, screen);</pre>
<pre>+        mh = texth(&brush.font);</pre>
<pre>+</pre>
<pre>+        win = XCreateWindow(dpy, root, mx, my, mw, mh, 0,</pre>
<pre>+                        DefaultDepth(dpy, screen), CopyFromParent,</pre>
<pre>+                        DefaultVisual(dpy, screen),</pre>
<pre>+                        CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);</pre>
<pre>+        XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm));</pre>
<pre>+        XFlush(dpy);</pre>
<pre>+</pre>
<pre>+        /* pixmap */</pre>
<pre>+        brush.gc = XCreateGC(dpy, root, 0, 0);</pre>
<pre>+        brush.drawable = XCreatePixmap(dpy, win, mw, mh,</pre>
<pre>+                        DefaultDepth(dpy, screen));</pre>
<pre>+        XFlush(dpy);</pre>
<pre>+</pre>
<pre>+        if(maxname)</pre>
<pre>+                cw = textw(&brush.font, maxname) + brush.font.height;</pre>
<pre>+        if(cw > mw / 3)</pre>
<pre>+                cw = mw / 3;</pre>
<pre>+</pre>
<pre>+        if(title) {</pre>
<pre>+                tw = textw(&brush.font, title) + brush.font.height;</pre>
<pre>+                if(tw > mw / 3)</pre>
<pre>+                        tw = mw / 3;</pre>
<pre>+        }</pre>
<pre>+</pre>
<pre>+        cmdw = title ? tw : cw;</pre>
<pre>+</pre>
<pre>+        text[0] = 0;</pre>
<pre>+        update_items(text);</pre>
<pre>+        XMapRaised(dpy, win);</pre>
<pre>+        draw_menu();</pre>
<pre>+        XFlush(dpy);</pre>
<pre>+</pre>
<pre>+        /* main event loop */</pre>
<pre>+        while(!done && !XNextEvent(dpy, &ev)) {</pre>
<pre>+                switch (ev.type) {</pre>
<pre>+                case KeyPress:</pre>
<pre>+                        kpress(&ev.xkey);</pre>
<pre>+                        break;</pre>
<pre>+                case Expose:</pre>
<pre>+                        if(ev.xexpose.count == 0)</pre>
<pre>+                                draw_menu();</pre>
<pre>+                        break;</pre>
<pre>+                default:</pre>
<pre>+                        break;</pre>
<pre>+                }</pre>
<pre>+        }</pre>
<pre>+</pre>
<pre>+        XUngrabKeyboard(dpy, CurrentTime);</pre>
<pre>+        XFreePixmap(dpy, brush.drawable);</pre>
<pre>+        XFreeGC(dpy, brush.gc);</pre>
<pre>+        XDestroyWindow(dpy, win);</pre>
<pre>+        XCloseDisplay(dpy);</pre>
<pre>+</pre>
<pre>+        return ret;</pre>
<pre>+}</pre>
<p><a href="/oddgopherpage/gopher.r-36.net:70/scm/dmenu/file/util.c.gph">diff --git a/util.c b/util.c </a><p>
<pre>t@@ -0,0 +1,68 @@</pre>
<pre>+/*</pre>
<pre>+ * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com></pre>
<pre>+ * See LICENSE file for license details.</pre>
<pre>+ */</pre>
<pre>+#include "dmenu.h"</pre>
<pre>+#include <stdarg.h></pre>
<pre>+#include <stdio.h></pre>
<pre>+#include <stdlib.h></pre>
<pre>+#include <string.h></pre>
<pre>+#include <sys/wait.h></pre>
<pre>+#include <unistd.h></pre>
<pre>+</pre>
<pre>+/* static */</pre>
<pre>+</pre>
<pre>+static void</pre>
<pre>+bad_malloc(unsigned int size)</pre>
<pre>+{</pre>
<pre>+        eprint("fatal: could not malloc() %u bytes\n", size);</pre>
<pre>+}</pre>
<pre>+</pre>
<pre>+/* extern */</pre>
<pre>+</pre>
<pre>+void *</pre>
<pre>+emalloc(unsigned int size)</pre>
<pre>+{</pre>
<pre>+        void *res = malloc(size);</pre>
<pre>+        if(!res)</pre>
<pre>+                bad_malloc(size);</pre>
<pre>+        return res;</pre>
<pre>+}</pre>
<pre>+</pre>
<pre>+void *</pre>
<pre>+emallocz(unsigned int size)</pre>
<pre>+{</pre>
<pre>+        void *res = calloc(1, size);</pre>
<pre>+</pre>
<pre>+        if(!res)</pre>
<pre>+                bad_malloc(size);</pre>
<pre>+        return res;</pre>
<pre>+}</pre>
<pre>+</pre>
<pre>+void</pre>
<pre>+eprint(const char *errstr, ...)</pre>
<pre>+{</pre>
<pre>+        va_list ap;</pre>
<pre>+</pre>
<pre>+        va_start(ap, errstr);</pre>
<pre>+        vfprintf(stderr, errstr, ap);</pre>
<pre>+        va_end(ap);</pre>
<pre>+        exit(EXIT_FAILURE);</pre>
<pre>+}</pre>
<pre>+</pre>
<pre>+char *</pre>
<pre>+estrdup(const char *str)</pre>
<pre>+{</pre>
<pre>+        void *res = strdup(str);</pre>
<pre>+        if(!res)</pre>
<pre>+                bad_malloc(strlen(str));</pre>
<pre>+        return res;</pre>
<pre>+}</pre>
<pre>+</pre>
<pre>+void</pre>
<pre>+swap(void **p1, void **p2)</pre>
<pre>+{</pre>
<pre>+        void *tmp = *p1;</pre>
<pre>+        *p1 = *p2;</pre>
<pre>+        *p2 = tmp;</pre>
<pre>+}</pre>
<pre>.
</pre>
<pre></pre>
</div>

			
			<hr class="afdisplay Art random-wjM7UhpHCI"><h5 class="display-zone-ad-title">AD:</h5><div id="display-zone" style="background-image: url('');"><a href='?oddoutbound=patreon.com/oddnugget'><h4>Join OddNugget on Patreon for free stuff!</h4></a></div><hr class="afdisplay">
		</div>	 
	</article> 

	<!-- Footer Area -->
	<div id="site-footer">
		<div id="stickyfoot">
			<div id="adbox-menu">
				<h5>AD:</h5><h5 id="footer-adclosebtn">X</h5>
			</div>
			<hr class="afstickydisplay Business random-qc2xZMEIUH"><div class="display-zone-sticky" style="background-image: url('');"><a href='?oddoutbound=https://tykr.com/?gr_pk=yQPZ&gr_uid=lJX2'><h6>Investing? Choose stocks with AI!</h6></a></div><hr class="afstickydisplay">
		</div>
		<div class="action-menu">
			<div id="notification-menu" class="sub-menu-div invisible">
				<h5 id="notification-menu-close-btn" onclick="hideNotification()">X</h5>
			</div>
			<input type="text" name="alias" placeholder="NAME...">
			<input type="email" name="email" placeholder="EMAIL...">
			<button type="button" name="join" onclick="signUp()">[JOIN]</button>
			<button type="button" name="login" onclick="logIn()" class="invisible">[LOGIN]</button>
		</div>
		<h4 id="clicksignup" onclick="switchSignup()" style="display: none;">NEW HERE? CLICK TO SIGN UP</h4>
		<h4 id="clickjoin" onclick="switchLogin()">ALREADY JOINED? CLICK TO LOGIN</h4>
	</div>

	<div id="footer" class="">
	</div>

  <!-- Javascript -->

	<script type='text/javascript'>
///////////////////////////
// Msc. Functionality
///////////////////////////

// Youtube Img to Embed onclick function
function ytImgtoEmbed(event) {
	//console.log(event.target);

	// Regex for youtube img url ID
	let reYtId = /ytimg.com\/vi\/(.*)\/mqdefault/;

	// Grab img url ID from ytimg in document (onclick)
	let regmatch = event.target.src.match(reYtId);
	//console.log("Match: " + regmatch[1]); 

	// Insert into embed code 
	let embed = document.createElement("IFRAME");
	embed.width = 560;
	embed.height = 415;
	embed.src = "https://www.youtube.com/embed/" + regmatch[1] + "?autoplay=1";
	//console.log(embed);

	// Replace img parent div with embed
	event.target.parentElement.replaceWith(embed);	
}

// Soundcloud Img to Embed onclick function
function sndImgtoEmbed(event) {
	//console.log(event.target);

	// Grab song ID from element dataset in document (onclick)
	let songID = event.target.dataset.songid;
	//console.log("songID: " + songID);

	// Insert into embed code 
	let embed = document.createElement("IFRAME");
	embed.width = 560;
	embed.height = 415;
	embed.src = "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/" + songID + "&color=%23ff5500&auto_play=true&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true";
	//console.log(embed);

	// Replace img parent div with embed
	event.target.parentElement.replaceWith(embed);	
}

// Bandcamp Img to Embed onclick function
function bandImgtoEmbed(event) {
	//console.log(event.target);

	// Grab song ID from element dataset in document (onclick)
	let songID = event.target.dataset.songid;
	//console.log("songID: " + songID);

	// Insert into embed code 
	let embed = document.createElement("IFRAME");
	embed.width = 560;
	embed.height = 415;
	embed.src = "https://bandcamp.com/EmbeddedPlayer/" + songID + "/size=large/bgcol=ffffff/linkcol=0687f5/artwork=small/transparent=true/";
	//console.log(embed);

	// Replace img parent div with embed
	event.target.parentElement.replaceWith(embed);	
}

// Non-YT Video Img to Embed onclick function
function kickImgtoEmbed(event) {
	//console.log(event.target);

	// Grab video URL from element dataset in document (onclick)
	let videoURL = event.target.dataset.url;
	//console.log("URL: " + videoURL);

	// Insert into embed code 
	let embed = document.createElement("VIDEO");
	embed.class = "";
	embed.width = 560;
	embed.height = 415;
	embed.controls = "controls";
	embed.autoplay = "autoplay";
	embed.src = videoURL;
	//console.log(embed);

	// Replace img parent div with embed
	event.target.parentElement.replaceWith(embed);	
}









///////////////////////////
// Menus
///////////////////////////

// 	vars for later

//		top menu elems
let mainMenu = document.getElementById("header-main-menu");
let adCloseBtn = document.getElementById("footer-adclosebtn");
let scrollTopBtn = document.getElementById("header-top-button"); // get scroll to top button
let contactBtn = document.getElementById("header-contact");
let privacyBtn = document.getElementById("header-privacy");
let mastheadBtn = document.getElementById("header-masthead");
let logoArea = document.getElementById("header-logo-area");
//let logo = document.getElementById("header-logo");

//		viewport/screen vars
let offheight = document.body.offsetHeight

//		bottom menu elems (login/join)
let clksignup = document.getElementById("clicksignup");
let clkjoin = document.getElementById("clickjoin");
let actionFormEmail = document.querySelector('[name="email"]');
let actionFormAlias = document.querySelector('[name="alias"]');
let actionFormLogin = document.querySelector('[name="login"]');
let actionFormJoin = document.querySelector('[name="join"]');

//		bottom menu elems (user)

//		main menu
let actionMenu = document.getElementById("action-menu");
if (actionMenu !== null) {
	var actionChildren = actionMenu.children; // "global"

	//		admin detection
	var adminItUp = false; // "global"
	if (actionChildren.length === 7) {adminItUp = true;}
}

//			lvl1
let actionFormBalanceIcon = document.getElementById("balance-icon");
let actionFormAccountIcon = document.getElementById("account-icon");
let actionFormAdsIcon = document.getElementById("ads-icon");
let actionFormChatIcon = document.getElementById("chat-icon");
let actionFormLogoutIcon = document.getElementById("logout-icon");

//			lvl2
let actionFormNotificationMenu = document.getElementById("notification-menu");
let actionFormNotificationMenuCloseBtn = document.getElementById("notification-menu-close-btn");

if (adminItUp === true) {var actionFormAdminMenu = document.getElementById("admin-menu");} // "global"
let actionFormBalanceMenu = document.getElementById("balance-menu");
let actionFormAccountMenu = document.getElementById("account-menu");
let actionFormAdsMenu = document.getElementById("ads-menu");
let actionFormChatMenu = document.getElementById("chat-menu");

let actionFormBalanceMenuElems = document.querySelectorAll(".balance-menu");
let actionFormAccountMenuElems = document.querySelectorAll(".account-menu");
let actionFormAdsMenuElems = document.querySelectorAll(".ads-menu");
let actionFormChatMenuElems = document.querySelectorAll(".chat-menu");
//let actionFormAdMenuUserAds = document.querySelectorAll(".user-ad-info");
//let actionFormAdMenuUserAds = document.getElementById("user-ads");
let actionFormNewAdMenuCreateBtn = document.getElementById("create-ad-btn");

let actionFormNewMsgForm = document.getElementById("new-msg-form");
let actionFormNewMsgFormBtn = document.getElementById("new-msg-form-btn");

//			lvl3
let actionFormNewAdMenuElems = document.querySelectorAll(".new-ad-menu");
let actionFormNewAdMenuAdTit = document.getElementById("new-ad-text");
let actionFormNewAdMenuAdURL = document.getElementById("new-ad-url");
let actionFormNewAdMenuAdCats = document.getElementById("new-ad-cats");
let actionFormNewAdMenuSubmit = document.getElementById("new-ad-submit");

let actionFormAdMenuAdListTitle = document.getElementById("ad-list-title");
let actionFormAdMenuAdList = document.getElementById("list-account-ads");
let actionFormAdMenuUserAds = document.getElementById("user-ads");
if (adminItUp === true) {
	var actionFormAdMenuAdListAll = document.getElementById("list-all-ads");
	var actionFormAdMenuAdListAllTitle = document.getElementById("ad-list-title-all");
	var actionFormAdMenuAllAds = document.getElementById("sitewide-ads");
}
if (adminItUp === true) {
	//actionFormAdMenuUserAds.style.height = "7em";
	//actionFormAdMenuAllAds.style.height = "7em";
}
let actionFormAdMenuAdContainers = document.querySelectorAll(".user-ad-container");
let actionFormAdMenuAdBackBtns = document.querySelectorAll(".user-ad-info-back");

let actionFormAdMenuAdActivateBtns = document.querySelectorAll(".user-activate-ad");
let actionFormAdMenuAdDeactivateBtns = document.querySelectorAll(".user-deactivate-ad");
let actionFormAdMenuAdUpdateBtns = document.querySelectorAll(".user-update-ad");
let actionFormAdMenuAdDeleteBtns = document.querySelectorAll(".user-delete-ad");

let actionFormInbox = document.getElementById("user-inbox");
let actionFormOutbox = document.getElementById("user-outbox");
let actionFormInboxTit = document.getElementById("user-inbox-title");
let actionFormOutboxTit = document.getElementById("user-outbox-title");
let actionFormInboxMsgs = document.querySelectorAll(".inbox-msg");
let actionFormOutboxMsgs = document.querySelectorAll(".outbox-msg");
let actionFormInboxBackBtns = document.querySelectorAll(".user-inbox-back-btn");
let actionFormOutboxBackBtns = document.querySelectorAll(".user-outbox-back-btn");
let actionFormInboxReplyBtns = document.querySelectorAll(".inbox-reply-btn");
let actionFormNewMsgFormFrom = document.getElementById("new-msg-from");
let actionFormNewMsgFormTo = document.getElementById("new-msg-to");
let actionFormNewMsgFormParent = document.getElementById("new-msg-parent");
let actionFormNewMsgFormTitle = document.getElementById("new-msg-title");
let actionFormNewMsgFormContent = document.getElementById("new-msg-content");
let actionFormNewMsgSendBtn = document.getElementById("new-msg-send-btn");

//console.log("Here are the user ad elements:")
//console.log(actionFormAdMenuUserAds)

//		bottom menu elems (admin)


// Top Menu -------------------------------------------

//	Scroll to Top Button
function scrollToTop() {
	//console.log("scrolling to top!");
	window.scroll(0, 0);
}

// Action Menu -------------------------------------------

//	Notifications functionality

function showNotification(msg) {
	//
	let msginsert = document.createElement("h3");
	msginsert.textContent = msg;
	msginsert.classList.add("notification-txt");

	//
	actionFormNotificationMenu.appendChild(msginsert);

	//
	actionFormNotificationMenu.classList.remove("invisible");
}

function hideNotification() {
	//
	let notifs = actionFormNotificationMenu.getElementsByClassName("notification-txt");

	//
	for (let st = notifs.length; st > 0; st--) {
			notifs[st - 1].remove();
	}

	//
	actionFormNotificationMenu.classList.add("invisible");
}

//	Adbox Functions
adCloseBtn.onclick = function closeAdBox() {
	document.getElementById("stickyfoot").style.display = "none";
	//console.log('Closing Adbox');
}

//	sign up / login form functionality

function switchLogin() {
	//
	clksignup.style.display = "block";
	clkjoin.style.display = "none";

	actionFormAlias.style.display = "none";
	actionFormEmail.style.width = "60%";

	actionFormJoin.classList.add("invisible");
	actionFormLogin.classList.remove("invisible");
}

function switchSignup() {
	//
	clksignup.style.display = "none";
	clkjoin.style.display = "";

	actionFormAlias.style.display = "";
	actionFormEmail.style.width = "35%";

	actionFormJoin.classList.remove("invisible");
	actionFormLogin.classList.add("invisible");
}

function signUp() {
	showNotification("SIGNING UP...")

	//
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "signup",
			Email: actionFormEmail.value,
			Alias: actionFormAlias.value
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext)
	});
}

function logIn() {
	showNotification("LOGGING IN...")

	//
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "login",
			Email: actionFormEmail.value,
			//Alias: actionFormAlias.value
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext)
	});
}

//	logged-in menu functionality

function showBalanceInfo() {
	//console.log("showing balance info...")
	//
	let visi = false;
	if (actionFormBalanceMenu.classList.contains("invisible") === true) {
		visi = true
	}

	//
	if (visi === true) {
		actionFormBalanceMenu.classList.remove("invisible");
	} else {
		actionFormBalanceMenu.classList.add("invisible");
	}

	//
//	for (let it = 0; it < actionFormBalanceMenuElems.length; it++) {
		//
//		if (visi === true) {
//			actionFormBalanceMenuElems[it].classList.remove("invisible");
//		} else {
//			actionFormBalanceMenuElems[it].classList.add("invisible");
//		}
//	}

	//
	if (adminItUp === true) {
		if (actionFormAdminMenu.classList.contains("invisible") !== true) {
			actionFormAdminMenu.classList.add("invisible");
		}
	}
	if (actionFormAccountMenu.classList.contains("invisible") !== true) {
		actionFormAccountMenu.classList.add("invisible");
	}
	if (actionFormAdsMenu.classList.contains("invisible") !== true) {
		actionFormAdsMenu.classList.add("invisible");
	}
	if (actionFormChatMenu.classList.contains("invisible") !== true) {
		actionFormChatMenu.classList.add("invisible");
	}
}

function showAccountInfo() {
	//
	let visi = false;
	if (actionFormAccountMenu.classList.contains("invisible") === true) {
		visi = true
	}

	//
	if (visi === true) {
		actionFormAccountMenu.classList.remove("invisible");
	} else {
		actionFormAccountMenu.classList.add("invisible");
	}

	//
//	for (let it = 0; it < actionFormAccountMenuElems.length; it++) {
//		if (visi === true) {
//			actionFormAccountMenuElems[it].classList.remove("invisible");
//		} else {
//			actionFormAccountMenuElems[it].classList.add("invisible");
//		}
//	}

	//
	if (adminItUp === true) {
		if (actionFormAdminMenu.classList.contains("invisible") !== true) {
			actionFormAdminMenu.classList.add("invisible");
		}
	}
	if (actionFormBalanceMenu.classList.contains("invisible") !== true) {
		actionFormBalanceMenu.classList.add("invisible");
	}
	if (actionFormAdsMenu.classList.contains("invisible") !== true) {
		actionFormAdsMenu.classList.add("invisible");
	}
	if (actionFormChatMenu.classList.contains("invisible") !== true) {
		actionFormChatMenu.classList.add("invisible");
	}
}

function showAdsInfo() {
	// if 
	let visi = false;
	if (actionFormAdsMenu.classList.contains("invisible") === true) {
		visi = true;
	}

	//
	if (visi === true) {
		actionFormAdsMenu.classList.remove("invisible");
	} else {
		actionFormAdsMenu.classList.add("invisible");
	}

	//
	if (adminItUp === true) {
		if (actionFormAdminMenu.classList.contains("invisible") !== true) {
			actionFormAdminMenu.classList.add("invisible");
		}
	}
	if (actionFormBalanceMenu.classList.contains("invisible") !== true) {
		actionFormBalanceMenu.classList.add("invisible");
	}
	if (actionFormAccountMenu.classList.contains("invisible") !== true) {
		actionFormAccountMenu.classList.add("invisible");
	}
	if (actionFormChatMenu.classList.contains("invisible") !== true) {
		actionFormChatMenu.classList.add("invisible");
	}
}

function getNewAdForm() {
	//	identify ad list that should be visible
	let listaccount = document.getElementById("list-account-ads");
	let visaccount = false;
	
	if (listaccount.classList.contains("invisible") === true) {
		visaccount = true;
	}

	//
	let visi = false;
	if (actionFormNewAdMenuElems[0].classList.contains("invisible") === true) {
		visi = true;
	}

	//
	for (let it = 0; it < actionFormNewAdMenuElems.length; it++) {
		if (visi === true) {
			actionFormNewAdMenuElems[it].classList.remove("invisible");
			actionFormNewAdMenuCreateBtn.textContent = "[CANCEL]";

			actionFormAdMenuAdList.classList.add("invisible");
			actionFormAdMenuAdListTitle.classList.add("invisible");
			if (adminItUp === true) {
				actionFormAdMenuAdListAll.classList.add("invisible");
				actionFormAdMenuAdListAllTitle.classList.add("invisible");
			}
			//actionFormAdMenuUserAds.classList.add("invisible")
			//for (let iter = 0; iter < actionFormAdMenuUserAds.length; iter++) {
			//	actionFormAdMenuUserAds[iter].classList.add("invisible");
			//}
		} else {
			actionFormNewAdMenuElems[it].classList.add("invisible");
			actionFormNewAdMenuCreateBtn.textContent = "[CREATE A NEW AD]";

			actionFormAdMenuAdList.classList.remove("invisible");
			actionFormAdMenuAdListTitle.classList.remove("invisible");
			if (adminItUp === true) {
				if (visaccount !== true) {
					actionFormAdMenuAdListAll.classList.remove("invisible");
					//actionFormAdMenuAdListAllTitle.classList.remove("invisible");
				}
			}
			//actionFormAdMenuUserAds.classList.remove("invisible")
			//for (let iter = 0; iter < actionFormAdMenuUserAds.length; iter++) {
			//	actionFormAdMenuUserAds[iter].classList.remove("invisible");
			//}
		}
	}
}

function createAd() {
	showNotification("CREATING AD...")

	//
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "createad",
			AdObCoNa: actionFormNewAdMenuAdCats.value,
			AdLnkURL: actionFormNewAdMenuAdURL.value,
			AdLnkTit: actionFormNewAdMenuAdTit.value,
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext)
	});
}

function showAdInfo(event) {
	//actionFormAdMenuAdContainers
	//console.log("An ad has been clicked in user's ad list!")
	//console.log(this.parentElement.parentElement)

	//
	for (let itty = 0; itty < actionFormAdMenuAdContainers.length; itty++) {
		//
		if (actionFormAdMenuAdContainers[itty] !== this) {
			actionFormAdMenuAdContainers[itty].classList.add("invisible");
		}
	}
	
	//	render contents of ads menu invisible 
	//		ignore current ad, and current ad's container
	for (let itto = 0; itto < actionFormAdsMenu.children.length; itto++) {
		if (actionFormAdsMenu.children[itto] !== this && actionFormAdsMenu.children[itto].id !== this.parentElement.parentElement.id) {
			//
			actionFormAdsMenu.children[itto].classList.add("invisible");
		}
	}

	//
	for (let itit = 0; itit < this.children.length; itit++) {
		if (this.children[itit].classList[0] !== "user-ad-info-id" || adminItUp === true) {
			this.children[itit].classList.remove("invisible");
		}
	}

	//	modify #list-all-ads/#list-account-ads dimensions
	this.parentElement.parentElement.style.width = "100%";
	this.parentElement.parentElement.style.height = "30em";

	this.parentElement.style.height = "100%";
	this.parentElement.style.display = "flex";
	this.parentElement.style.flexDirection = "column";
	this.parentElement.style.justifyContent = "center";
	this.parentElement.style.alignItems = "center";

	this.style.height = "100%";
	this.removeEventListener("click", showAdInfo);
	this.classList.remove("user-ad-container-hov");
	
	event.stopPropagation();
}

function hideAdInfo(event) {
	//console.log("Hiding ad info!")

	//	identify list that should be kept invisible
	//let currentListID = this.parentElement.parentElement.parentElement.id
	//let otherListID = ""

	//console.log("hideAdInfo current list ID is: ")
	//console.log(currentListID)

	//if (currentListID == "list-account-ads") {
	//	otherListID = "list-all-ads"
	//} else {
	//	otherListID = "list-account-ads"
	//}

	//
	for (let itty = 0; itty < actionFormAdMenuAdContainers.length; itty++) {
		//
		if (actionFormAdMenuAdContainers[itty] !== this.parentElement) {
			actionFormAdMenuAdContainers[itty].classList.remove("invisible");
		}
	}
	
	//	render ad menu content visible again
	//		ignore current ad and its parent element, ignore other list 
	for (let itto = 0; itto < actionFormAdsMenu.children.length; itto++) {
		if (actionFormAdsMenu.children[itto] !== this.parentElement && actionFormAdsMenu.children[itto].id !== "list-all-ads" && actionFormAdsMenu.children[itto].id !== "list-account-ads" && actionFormAdsMenu.children[itto].id !== "ad-list-title-all") {
			//
			actionFormAdsMenu.children[itto].classList.remove("invisible");
		}
	}

	//
	for (let itit = 0; itit < this.parentElement.children.length; itit++) {
		if (this.parentElement.children[itit].classList[0] !== "" && this.parentElement.children[itit].classList[1] !== "user-ad-info-date" && this.parentElement.children[itit].classList[1] !== "user-ad-status-indicators" && this.parentElement.children[itit].classList[0] !== "user-ad-info-title") {
			this.parentElement.children[itit].classList.add("invisible");
		}
	}

	//
	this.parentElement.parentElement.parentElement.style.width = "";

	this.parentElement.parentElement.style.height = "";
	if (adminItUp === true) {
		actionFormAdMenuUserAds.style.height = "90%";
		actionFormAdMenuAllAds.style.height = "90%";
	}
	this.parentElement.parentElement.style.display = "";
	this.parentElement.parentElement.style.flexDirection = "";
	this.parentElement.parentElement.style.justifyContent = "";
	this.parentElement.parentElement.style.alignItems = "";

	this.parentElement.style.height = "";
	this.parentElement.addEventListener("click", showAdInfo);
	this.parentElement.classList.add("user-ad-container-hov");

	event.stopPropagation();
}

function swapAdTabs(elem) {
	console.log(elem)

	//
	let visi = false;
	if (elem.textContent === "[SHOW YOUR ADS]") {
		visi = true;
	}

	if (visi === true) {
		elem.textContent = "[SHOW ALL ADS]";

		document.getElementById("list-all-ads").classList.add("invisible");
		document.getElementById("list-account-ads").classList.remove("invisible");
	} else {
		elem.textContent = "[SHOW YOUR ADS]";

		document.getElementById("list-all-ads").classList.remove("invisible");
		document.getElementById("list-account-ads").classList.add("invisible");
	}

}

function ActivateAd() {
	showNotification("ACTIVATING AD...");

	//
	let lnkid = ""
	for (let it = 0; it < this.parentElement.parentElement.children.length; it++) {
		if (this.parentElement.parentElement.children[it].classList.contains("user-ad-info-id") === true) {
			lnkid = this.parentElement.parentElement.children[it].textContent;
		}
	}

	//
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "activatead",
			AdLnkID: lnkid,
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext)
	});
}

function DeactivateAd() {
	showNotification("DEACTIVATING AD...");

	//
	let lnkid = ""
	for (let it = 0; it < this.parentElement.parentElement.children.length; it++) {
		if (this.parentElement.parentElement.children[it].classList.contains("user-ad-info-id") === true) {
			lnkid = this.parentElement.parentElement.children[it].textContent;
		}
	}

	//
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "deactivatead",
			AdLnkID: lnkid,
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext)
	});
}

function UpdateAd() {
	showNotification("UPDATING AD...");

	//
	let lnkid = ""
	let lnktit = ""
	let lnkurl = ""

	for (let it = 0; it < this.parentElement.parentElement.children.length; it++) {
		if (this.parentElement.parentElement.children[it].classList.contains("user-ad-info-id") === true) {
			lnkid = this.parentElement.parentElement.children[it].textContent;
		} else if (this.parentElement.parentElement.children[it].classList.contains("user-ad-info-title") === true) {
			lnktit = this.parentElement.parentElement.children[it].value;
		} else if (this.parentElement.parentElement.children[it].classList.contains("user-ad-info-url") === true) {
			lnkurl = this.parentElement.parentElement.children[it].value;
		}
	}

	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "updatead",
			AdLnkID: lnkid,
			AdLnkURL: lnkurl,
			AdLnkTit: lnktit,
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext)
	});
}

function DeleteAd() {
	showNotification("DELETING AD...");

	//
	let lnkid = ""
	for (let it = 0; it < this.parentElement.parentElement.children.length; it++) {
		if (this.parentElement.parentElement.children[it].classList.contains("user-ad-info-id") === true) {
			lnkid = this.parentElement.parentElement.children[it].textContent;
		}
	}

	//
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "deletead",
			AdLnkID: lnkid,
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext)
	});
}

//		chat funtionality

function showChatInfo() {
	//
	let visi = false;
	if (actionFormChatMenu.classList.contains("invisible") === true) {
		visi = true;
	}

	//
//	let contact = false;
//	if (actionFormNewMsgForm.classList.contains("invisible") !== true) {contact = true;}
//	console.log(contact)

	//
	if (visi === true) {
		actionFormChatMenu.classList.remove("invisible");
	} else {
		actionFormChatMenu.classList.add("invisible");
	}

	//
//	for (let it = 0; it < actionFormChatMenuElems.length; it++) {
//		if (visi === true) {
//			if (actionFormChatMenuElems[it].id !== "new-msg-form") {
//				actionFormChatMenuElems[it].classList.remove("invisible");
//			} 
//		} else {
//			actionFormChatMenuElems[it].classList.add("invisible");
//		}
//	}

	//
	if (adminItUp === true) {
		if (actionFormAdminMenu.classList.contains("invisible") !== true) {
			actionFormAdminMenu.classList.add("invisible");
		}
	}
	if (actionFormBalanceMenu.classList.contains("invisible") !== true) {
		actionFormBalanceMenu.classList.add("invisible");
	}
	if (actionFormAccountMenu.classList.contains("invisible") !== true) {
		actionFormAccountMenu.classList.add("invisible");
	}
	if (actionFormAdsMenu.classList.contains("invisible") !== true) {
		actionFormAdsMenu.classList.add("invisible");
	}
}

function getNewMsgForm() {
	//
	let visi = false;
	if (actionFormNewMsgForm.classList.contains("invisible") === true) {
		visi = true;
	}

	//
	if (visi === true) {
		actionFormNewMsgForm.classList.remove("invisible");

		actionFormNewMsgFormBtn.textContent = "[BACK]";

		actionFormInbox.classList.add("invisible");
		actionFormOutbox.classList.add("invisible");
	} else {
		actionFormNewMsgForm.classList.add("invisible");

		if (adminItUp === true) {
			actionFormNewMsgFormBtn.textContent = "[SEND A MESSAGE]";
		} else {
			actionFormNewMsgFormBtn.textContent = "[CONTACT SUPPORT]";
		}

		actionFormInbox.classList.remove("invisible");
		actionFormOutbox.classList.remove("invisible");

		actionFormNewMsgFormParent.value = "";
		actionFormNewMsgFormTo.value = "";
		actionFormNewMsgSendBtn.textContent = "[SEND]";
	}
}

function sendMSG() {
	showNotification("SENDING MESSAGE...")

	//actionFormNewMsgForm
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "sendmsg",
			MsgFro: actionFormNewMsgFormFrom.value,
			MsgTo: actionFormNewMsgFormTo.value,
			MsgTit: actionFormNewMsgFormTitle.value,
			MsgCon: actionFormNewMsgFormContent.value,
			MsgPar: actionFormNewMsgFormParent.value,
			//MsgID: ,
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext);
	});
}

function readMSG(msgid, elem) {
	//showNotification("Reading a message...")

	let result = "";

	//actionFormNewMsgForm
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "readmsg",
			MsgID: msgid,
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		//showNotification(responsetext);

		if (responsetext == "read success") {
			//
			elem.textContent = "READ";
		}

	});

	//
	return result
}

function showInbox(event) {
	//
	let visi = false;
	if (this.textContent === "[VIEW INBOX]") {
		visi = true;
	}

	//
	for (let it = 0; it < this.parentElement.children.length; it++) {
		if (this.parentElement.children[it].classList.contains("user-inbox") === true) {
			if (visi === true) {
				this.parentElement.children[it].classList.remove("invisible");

				actionFormNewMsgFormBtn.classList.add("invisible");
				actionFormOutboxTit.classList.add("invisible");

				this.textContent = "[BACK]";

				//console.log("Showing user inbox!");
			} else {
				this.parentElement.children[it].classList.add("invisible");

				actionFormNewMsgFormBtn.classList.remove("invisible");
				actionFormOutboxTit.classList.remove("invisible");

				this.textContent = "[VIEW INBOX]";

				//console.log("Hiding user inbox!");
			}
		}
	}

	event.stopPropagation();
}

function showInboxMsg(event) {
	//
	let readstatus = this.getElementsByClassName("read-status-txt");

	if (readstatus[0].textContent === "UNREAD") {
		//console.log("This message is being opened for the first time!");
		
		//
		let msgid = this.getElementsByClassName("msg-id")[0].textContent;
		//console.log(msgid);

		//
		readMSG(msgid, readstatus[0]);
	}

	//
	actionFormInboxTit.classList.add("invisible");

	this.classList.remove("inbox-msg-hov")
	this.style.height = "90%";
	this.parentElement.style.justifyContent = "center";
	this.parentElement.style.height = "100%";

	for (let it = 0; it < actionFormInboxMsgs.length; it++) {
		//
		if (actionFormInboxMsgs[it] !== this) {
			actionFormInboxMsgs[it].classList.add("invisible");
		}
	}

	for (let ite = 0; ite < this.children.length; ite++) {
		if (this.children[ite].classList.contains("msg-content") || this.children[ite].classList.contains("msg-action-area") || this.children[ite].classList.contains("user-inbox-back-btn")) {
			this.children[ite].classList.remove("invisible");
		}
	}

	event.stopPropagation();
}

function hideInboxMsg(event) {
	//console.log("Hiding inbox!");
	//console.log(this);

	//
	actionFormInboxTit.classList.remove("invisible");

	this.parentElement.classList.add("inbox-msg-hov")
	this.parentElement.style.height = "auto";
	this.parentElement.parentElement.style.justifyContent = "";
	this.parentElement.parentElement.style.height = "25em";

	for (let it = 0; it < actionFormInboxMsgs.length; it++) {
		//
		if (actionFormInboxMsgs[it] !== this.parentElement) {
			actionFormInboxMsgs[it].classList.remove("invisible");
		}
	}

	for (let ite = 0; ite < this.parentElement.children.length; ite++) {
		if (this.parentElement.children[ite].classList.contains("msg-content") || this.parentElement.children[ite].classList.contains("msg-action-area") || this.parentElement.children[ite].classList.contains("user-inbox-back-btn")) {
			this.parentElement.children[ite].classList.add("invisible");
		}
	}

	event.stopPropagation();
}

function navToMsgFormReply(event) {
	//console.log("Navigating to new message form for reply!")

	//
	message = this.parentElement.parentElement;
	backbtn = message.getElementsByClassName("user-inbox-back-btn")[0];
	
	//
	userfrom = message.getElementsByClassName("msg-from")[0].textContent;
	parentid = message.getElementsByClassName("msg-id")[0].textContent;
	//console.log(parentid)

	//
	backbtn.click();
	actionFormInboxTit.click();
	actionFormNewMsgFormBtn.click();

	//
	actionFormNewMsgFormTo.value = userfrom;
	actionFormNewMsgFormParent.value = parentid;
	actionFormNewMsgSendBtn.textContent = "[SEND REPLY]";

	//
	event.stopPropagation();
}

function showOutbox(event) {
	//
	let visi = false;
	if (this.textContent === "[VIEW OUTBOX]") {
		visi = true;
	}

	//
	for (let it = 0; it < this.parentElement.children.length; it++) {
		if (this.parentElement.children[it].classList.contains("user-outbox") === true) {
			if (visi === true) {
				this.parentElement.children[it].classList.remove("invisible");

				actionFormNewMsgFormBtn.classList.add("invisible");
				actionFormInboxTit.classList.add("invisible");

				this.textContent = "[BACK]";

				//console.log("Showing user outbox!");
			} else {
				this.parentElement.children[it].classList.add("invisible");

				actionFormNewMsgFormBtn.classList.remove("invisible");
				actionFormInboxTit.classList.remove("invisible");

				this.textContent = "[VIEW OUTBOX]";
				//console.log("Hiding user outbox!");
			}
		}
	}

	event.stopPropagation();
}

function showOutboxMsg(event) {
	//
	actionFormOutboxTit.classList.add("invisible");

	this.classList.remove("outbox-msg-hov")
	this.style.height = "90%";
	this.parentElement.style.justifyContent = "center";
	this.parentElement.style.height = "100%";

	for (let it = 0; it < actionFormOutboxMsgs.length; it++) {
		//
		if (actionFormOutboxMsgs[it] !== this) {
			actionFormOutboxMsgs[it].classList.add("invisible");
		}
	}

	for (let ite = 0; ite < this.children.length; ite++) {
		if (this.children[ite].classList.contains("msg-content") || this.children[ite].classList.contains("msg-action-area") || this.children[ite].classList.contains("user-outbox-back-btn")) {
			this.children[ite].classList.remove("invisible");
		}
	}

	event.stopPropagation();
}

function hideOutboxMsg(event) {
	//console.log("Hiding outbox!")

	//
	actionFormOutboxTit.classList.remove("invisible");

	this.parentElement.classList.add("outbox-msg-hov")
	this.parentElement.style.height = "auto";
	this.parentElement.parentElement.style.justifyContent = "";
	this.parentElement.parentElement.style.height = "25em";

	for (let it = 0; it < actionFormOutboxMsgs.length; it++) {
		//
		if (actionFormOutboxMsgs[it] !== this.parentElement) {
			actionFormOutboxMsgs[it].classList.remove("invisible");
		}
	}

	for (let ite = 0; ite < this.parentElement.children.length; ite++) {
		if (this.parentElement.children[ite].classList.contains("msg-content") || this.parentElement.children[ite].classList.contains("user-outbox-back-btn")) {
			this.parentElement.children[ite].classList.add("invisible");
		}
	}

	event.stopPropagation();
}

//		logout functionality

function logOut() {
	showNotification("LOGGING OUT...")

	//actionFormNewMsgForm
	fetch(window.location.href + "?oddaccount=1", {
		method: "post",
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},

		//
		body: JSON.stringify({
			Action: "logout",
		})
	})

	.then(response => { 
		//
		//console.log(response)
		return response.text();
	})

	.then(responsetext => {
		//
		showNotification(responsetext);
	});
}

//		admin functionality

function showAdminInfo(elem) {
	//
	if (adminItUp === true) {
		//console.log("Admin menu detected!")

		//
		let visi = false;
		if (actionFormAdminMenu.classList.contains("invisible") === true) {
			visi = true;
		}

		//
		if (visi === true) {
			actionFormAdminMenu.classList.remove("invisible");
		} else {
			actionFormAdminMenu.classList.add("invisible");
		}

		//
		if (actionFormChatMenu.classList.contains("invisible") !== true) {
			actionFormChatMenu.classList.add("invisible");
		}
		if (actionFormBalanceMenu.classList.contains("invisible") !== true) {
			actionFormBalanceMenu.classList.add("invisible");
		}
		if (actionFormAccountMenu.classList.contains("invisible") !== true) {
			actionFormAccountMenu.classList.add("invisible");
		}
		if (actionFormAdsMenu.classList.contains("invisible") !== true) {
			actionFormAdsMenu.classList.add("invisible");
		}
	}
}

//			site ops

function openOpsMenu(elem) {
	//
	let visi = false;
	if (elem.textContent === "[SITEWIDE OPS]") {
		visi = true;
	}

	//
	let siteopschildren = elem.parentElement.children;
	let adminchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < siteopschildren.length; it++) {
			if (visi === true) {
				siteopschildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (siteopschildren[it] !== elem) {
					siteopschildren[it].classList.add("invisible");
					elem.textContent = "[SITEWIDE OPS]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.remove("invisible");
			}
		}
	}
}

function removeLinks(elem) {
	//
	if (elem.textContent === "[REMOVE ALL AD LINKS]") {
		//
		elem.textContent = "[TAP AGAIN TO CONFIRM]";
	} else {
		showNotification("SUBMITTING SITEWIDE OP REQUEST...")

		//actionFormNewMsgForm
		fetch(window.location.href + "?oddaccount=1", {
			method: "post",
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},

			//
			body: JSON.stringify({
				Action: "admin-remlnks",
			})
		})

		.then(response => { 
			//
			//console.log(response)
			return response.text();
		})

		.then(responsetext => {
			//
			showNotification(responsetext);
		});
	}
}

function convertPosts(elem) {
	//
	if (elem.textContent === "[UPDATE ALL POSTS TO CURRENT TEMPLATE]") {
		//
		elem.textContent = "[TAP AGAIN TO CONFIRM]";
	} else {
		showNotification("SUBMITTING SITEWIDE OP REQUEST...")

		//actionFormNewMsgForm
		fetch(window.location.href + "?oddaccount=1", {
			method: "post",
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},

			//
			body: JSON.stringify({
				Action: "admin-conposts",
			})
		})

		.then(response => { 
			//
			//console.log(response)
			return response.text();
		})

		.then(responsetext => {
			//
			showNotification(responsetext);
		});
	}
}

//			post utilities

function openArtList(elem) {
	//
	let visi = false;
	if (elem.textContent === "[POST UTILITIES]") {
		visi = true;
	}

	//
	let postutilschildren = elem.parentElement.children;
	let adminchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < postutilschildren.length; it++) {
			if (visi === true) {
				postutilschildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (postutilschildren[it] !== elem) {
					postutilschildren[it].classList.add("invisible");
					elem.textContent = "[POST UTILITIES]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.remove("invisible");
			}
		}
	}
}

function showUpMenu(elem) {
	//
	let visi = false;
	if (elem.textContent === "[POST UPLOADER]") {
		visi = true;
	}

	//
	let upmenuchildren = elem.parentElement.children;
	let postmenuchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < upmenuchildren.length; it++) {
			if (visi === true) {
				upmenuchildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (upmenuchildren[it] !== elem) {
					upmenuchildren[it].classList.add("invisible");
					elem.textContent = "[POST UPLOADER]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < postmenuchildren.length; dem++) {
			if (postmenuchildren[dem] !== elem.parentElement) {
				postmenuchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < postmenuchildren.length; dem++) {
			if (postmenuchildren[dem] !== elem.parentElement) {
				postmenuchildren[dem].classList.remove("invisible");
			}
		}
	}
}

function showTarUpMenu(elem) {
	//
	let visi = false;
	if (elem.textContent === "[TAR FILE UPLOADER]") {
		visi = true;
	}

	//
	let tarupmenuchildren = elem.parentElement.children;
	let postmenuchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < tarupmenuchildren.length; it++) {
			if (visi === true) {
				tarupmenuchildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (tarupmenuchildren[it] !== elem) {
					tarupmenuchildren[it].classList.add("invisible");
					elem.textContent = "[TAR FILE UPLOADER]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < postmenuchildren.length; dem++) {
			if (postmenuchildren[dem] !== elem.parentElement) {
				postmenuchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < postmenuchildren.length; dem++) {
			if (postmenuchildren[dem] !== elem.parentElement) {
				postmenuchildren[dem].classList.remove("invisible");
			}
		}
	}
}

function showPostLst(elem) {
	//
	let visi = false;
	if (elem.textContent === "[SCHEDULED POSTS]") {
		visi = true;
	}

	//
	let schedulechildren = elem.parentElement.children;
	let postmenuchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < schedulechildren.length; it++) {
			if (visi === true) {
				schedulechildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (schedulechildren[it] !== elem) {
					schedulechildren[it].classList.add("invisible");
					elem.textContent = "[SCHEDULED POSTS]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < postmenuchildren.length; dem++) {
			if (postmenuchildren[dem] !== elem.parentElement) {
				postmenuchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < postmenuchildren.length; dem++) {
			if (postmenuchildren[dem] !== elem.parentElement) {
				postmenuchildren[dem].classList.remove("invisible");
			}
		}
	}
}

function postUp(elem) {
	//
	if (elem.textContent === "[UPLOAD POST]") {
		//
		elem.textContent = "[TAP AGAIN TO CONFIRM]";
	} else {
		showNotification("SUBMITTING POST UPLOAD REQUEST...");

		let postflsfld = elem.parentElement.children[1];
		let postfls = postflsfld.files;

		//	set up an array of promises for multiple files
		let promises = [];
		
		//
		for (let file of postfls) {
			let filepromise = new Promise(resolve => {
				let reader = new FileReader();

				reader.readAsBinaryString(file);
				//reader.readAsArrayBuffer(file);
				reader.onload = () => resolve(btoa(reader.result));
			});

			promises.push(filepromise);
		}

		Promise.all(promises)

		.then(filearray => {
			//console.log(postfls);
			//console.log(filearray)

			let filenames = []

			for (let it = 0; it < postfls.length; it++) {filenames.push(postfls[it].name);}

			fetch(window.location.href + "?oddaccount=1", {
				method: "post",
				headers: {
					'Accept': 'application/json',
					'Content-Type': 'application/json'
				},

				//
				body: JSON.stringify({
					Action: "admin-postup",
					PostFlsStr: filearray,
					PostFlsNam: filenames,
				})
			})

			.then(response => { 
				//
				//console.log(response)
				return response.text();
			})

			.then(responsetext => {
				//
				showNotification(responsetext);
			});
		});
	}
}

//			traffic reports

function openTrafRepMenu(elem) {
	//
	let visi = false;
	if (elem.textContent === "[TRAFFIC REPORTS]") {
		visi = true;
	}

	//
	let trafficreportschildren = elem.parentElement.children;
	let adminchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < trafficreportschildren.length; it++) {
			if (visi === true) {
				trafficreportschildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (trafficreportschildren[it] !== elem) {
					trafficreportschildren[it].classList.add("invisible");
					elem.textContent = "[TRAFFIC REPORTS]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.remove("invisible");
			}
		}
	}
}

function getweekreport(elem) {
	//
	let visi = false;
	if (elem.textContent === "[VISITORS/VIEWS 7 DAYS]") {
		visi = true;
	}

	//
	let trafficreportschildren = elem.parentElement.children;
	let menuchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < trafficreportschildren.length; it++) {
			if (visi === true) {
				trafficreportschildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (trafficreportschildren[it] !== elem) {
					trafficreportschildren[it].classList.add("invisible");
					elem.textContent = "[VISITORS/VIEWS 7 DAYS]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < menuchildren.length; dem++) {
			if (menuchildren[dem] !== elem.parentElement) {
				menuchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < menuchildren.length; dem++) {
			if (menuchildren[dem] !== elem.parentElement) {
				menuchildren[dem].classList.remove("invisible");
			}
		}
	}

	if (visi === true) {
		//actionFormNewMsgForm
		fetch(window.location.href + "?oddaccount=1", {
			method: "post",
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},

			//
			body: JSON.stringify({
				Action: "admin-trafficrepwk",
			})
		})

		.then(response => { 
			//
			//console.log(response)
			jsondata = response.json(); // convert response to json
			return jsondata;
		})

		.then(responsejson => {
			//
			if (responsejson.length === 0) {
				showNotification("NO RESULTS WERE RETURNED.");
			} else {
				//
				console.log(responsejson);

				let datcon = document.querySelectorAll(".traffic-report-week-dates")[0];
				let viscon = document.querySelectorAll(".traffic-report-week-visitors")[0];
				let pagcon = document.querySelectorAll(".traffic-report-week-pageviews")[0];

				let datconclone = datcon.cloneNode();
				let visconclone = viscon.cloneNode();
				let pagconclone = pagcon.cloneNode();

				//	add titles
				let dattitle = document.createElement("h3");
				dattitle.textContent = "DATE";
				datconclone.appendChild(dattitle);

				let vistitle = document.createElement("h3");
				vistitle.textContent = "VISITORS";
				visconclone.appendChild(vistitle);

				let pagtitle = document.createElement("h3");
				pagtitle.textContent = "VIEWS";
				pagconclone.appendChild(pagtitle);

				for (let property in responsejson.Visitors) {
					//console.log(property + ": " + responsejson.Visitors[property])
					let date = document.createElement("p");
					date.textContent = property;
					datconclone.appendChild(date);

					let item = document.createElement("p");
					item.textContent = responsejson.Visitors[property];
					visconclone.appendChild(item);
				}

				for (let property in responsejson.Pageviews) {
					//console.log(property + ": " + responsejson.Visitors[property])
					let item = document.createElement("p");
					item.textContent = responsejson.Pageviews[property];
					pagconclone.appendChild(item);
				}

				//console.log(visconclone)
				datcon.parentNode.replaceChild(datconclone, datcon)
				viscon.parentNode.replaceChild(visconclone, viscon)
				pagcon.parentNode.replaceChild(pagconclone, pagcon)
			}

			//console.log(visconclone)
		});

		//console.log(visconclone)
	}
}

function getdayrefreport(elem) {
	//
	let visi = false;
	if (elem.textContent === "[REFERRERS CURRENT DAY]") {
		visi = true;
	}

	//
	let trafficreportschildren = elem.parentElement.children;
	let menuchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < trafficreportschildren.length; it++) {
			if (visi === true) {
				trafficreportschildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (trafficreportschildren[it] !== elem) {
					trafficreportschildren[it].classList.add("invisible");
					elem.textContent = "[REFERRERS CURRENT DAY]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < menuchildren.length; dem++) {
			if (menuchildren[dem] !== elem.parentElement) {
				menuchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < menuchildren.length; dem++) {
			if (menuchildren[dem] !== elem.parentElement) {
				menuchildren[dem].classList.remove("invisible");
			}
		}
	}

	if (visi === true) {
		//actionFormNewMsgForm
		fetch(window.location.href + "?oddaccount=1", {
			method: "post",
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},

			//
			body: JSON.stringify({
				Action: "admin-refrep",
			})
		})

		.then(response => { 
			//
			//console.log(response)
			jsondata = response.json(); // convert response to json
			return jsondata;
		})

		.then(responsejson => {
			//
			if (responsejson.length === 0) {
				showNotification("NO RESULTS WERE RETURNED.");
			} else {
				//
				console.log(responsejson);

				let urlcon = document.querySelectorAll(".referrer-report-day-urls")[0];
				let frecon = document.querySelectorAll(".referrer-report-day-frequency")[0];

				let urlconclone = urlcon.cloneNode();
				let freconclone = frecon.cloneNode();

				//	add titles
				let urltitle = document.createElement("h3");
				urltitle.textContent = "URLS";
				urlconclone.appendChild(urltitle);

				let fretitle = document.createElement("h3");
				fretitle.textContent = "FREQUENCY";
				freconclone.appendChild(fretitle);

				for (let it = 0; it < responsejson["URLs"].length; it++) {
					//console.log("A URL: " + responsejson["URLs"][it])
					let url = document.createElement("p");
					url.textContent = responsejson["URLs"][it];
					urlconclone.appendChild(url);

					let item = document.createElement("p");
					item.textContent = responsejson["Frequency"][it];
					freconclone.appendChild(item);
				}

				//console.log(visconclone)
				urlcon.parentNode.replaceChild(urlconclone, urlcon)
				frecon.parentNode.replaceChild(freconclone, frecon)
			}

			//console.log(visconclone)
		});

		//console.log(visconclone)
	}
}

//			users utilities

function openUseRepMenu(elem) {
	//
	let visi = false;
	if (elem.textContent === "[USER UTILITIES]") {
		visi = true;
	}

	//
	let trafficreportschildren = elem.parentElement.children;
	let adminchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < trafficreportschildren.length; it++) {
			if (visi === true) {
				trafficreportschildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (trafficreportschildren[it] !== elem) {
					trafficreportschildren[it].classList.add("invisible");
					elem.textContent = "[USER UTILITIES]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.remove("invisible");
			}
		}
	}
}

function getnonadminreport(elem) {
	//
	let visi = false;
	if (elem.textContent === "[ALL USERS REPORT (NONADMIN)]") {
		visi = true;
	}

	//
	let trafficreportschildren = elem.parentElement.children;
	let menuchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < trafficreportschildren.length; it++) {
			if (visi === true) {
				trafficreportschildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (trafficreportschildren[it] !== elem) {
					trafficreportschildren[it].classList.add("invisible");
					elem.textContent = "[ALL USERS REPORT (NONADMIN)]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < menuchildren.length; dem++) {
			if (menuchildren[dem] !== elem.parentElement) {
				menuchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < menuchildren.length; dem++) {
			if (menuchildren[dem] !== elem.parentElement) {
				menuchildren[dem].classList.remove("invisible");
			}
		}
	}

	if (visi === true) {
		//actionFormNewMsgForm
		fetch(window.location.href + "?oddaccount=1", {
			method: "post",
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},

			//
			body: JSON.stringify({
				Action: "admin-userstotal",
			})
		})

		.then(response => { 
			//
			//console.log(response)
			jsondata = response.json(); // convert response to json
			return jsondata;
		})

		.then(responsejson => {
			//
			if (responsejson.length === 0) {
				showNotification("NO RESULTS WERE RETURNED.");
			} else {
				//
				console.log(responsejson);

				let totcon = document.querySelectorAll(".user-report-nonadmin-total")[0];
				let actcon = document.querySelectorAll(".user-report-nonadmin-active")[0];
				let allcon = document.querySelectorAll(".user-report-nonadmin-all")[0];

				let totconclone = totcon.cloneNode();
				let actconclone = actcon.cloneNode();
				let allconclone = allcon.cloneNode();

				//	add titles
				let tottitle = document.createElement("h3");
				tottitle.textContent = "TOTAL";
				totconclone.appendChild(tottitle);

				let acttitle = document.createElement("h3");
				acttitle.textContent = "ACTIVE";
				actconclone.appendChild(acttitle);

				let alltitle = document.createElement("h3");
				alltitle.textContent = "ALL USERS";
				allconclone.appendChild(alltitle);

				for (let it = 0; it < responsejson.Users.length; it++) {
					//console.log(property + ": " + responsejson.TotalUsers[property])
					//console.log(property + ": " + responsejson.ActiveUsers[property])
					//console.log(property + ": " + responsejson.Users[property])
					let all = document.createElement("p");
					all.textContent = responsejson.Users[it].Email;
					if (responsejson.Users[it].IsActiveBool > 0) {
						all.textContent += " A"
					} else {
						all.textContent += " I"
					}

					allconclone.appendChild(all);
				}

				let total = document.createElement("p");
				total.textContent = responsejson.TotalUsers;
				totconclone.appendChild(total);

				let active = document.createElement("p");
				active.textContent = responsejson.ActiveUsers;
				actconclone.appendChild(active);

				//console.log(visconclone)
				totcon.parentNode.replaceChild(totconclone, totcon)
				actcon.parentNode.replaceChild(actconclone, actcon)
				allcon.parentNode.replaceChild(allconclone, allcon)
			}

			//console.log(visconclone)
		});

		//console.log(visconclone)
	}
}

function getcredusrlst25menu(elem) {
	//
	let visi = false;
	if (elem.textContent === "[CREDIT USERS $25]") {
		visi = true;
	}

	//
	let trafficreportschildren = elem.parentElement.children;
	let adminchildren = elem.parentElement.parentElement.children;

	//
	for (let it = 0; it < trafficreportschildren.length; it++) {
			if (visi === true) {
				trafficreportschildren[it].classList.remove("invisible");
				elem.textContent = "[BACK]";
			} else {
				if (trafficreportschildren[it] !== elem) {
					trafficreportschildren[it].classList.add("invisible");
					elem.textContent = "[CREDIT USERS $25]";
				}
			}
	}

	if (visi === true) {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.add("invisible");
			}
		}
	} else {
		for (let dem = 0; dem < adminchildren.length; dem++) {
			if (adminchildren[dem] !== elem.parentElement) {
				adminchildren[dem].classList.remove("invisible");
			}
		}
	}
}

function credusrlst25(elem) {
	//
	let visi = false;
	if (elem.textContent === "[SUBMIT EMAILS]") {
		visi = true;
	}

	if (visi === true) {
		//actionFormNewMsgForm
		fetch(window.location.href + "?oddaccount=1", {
			method: "post",
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},

			//
			body: JSON.stringify({
				Action: "admin-userscred25",
				UsrLst: document.getElementById("usr-cred-lst-25-mls").value,
			})
		})

		.then(response => { 
			//console.log(response)

			return response.text();
		})

		.then(responsetext => {
			showNotification(responsetext)
		})

		//console.log(visconclone)
	}
}

//			ads

function approveAd(elem) {
	//
	if (elem.textContent === "[APPROVE]") {
		//
		elem.textContent = "[TAP AGAIN TO CONFIRM]";
	} else {
		showNotification("SUBMITTING AD APPROVAL REQUEST...")

		//
		let lnkid = ""
		for (let it = 0; it < elem.parentElement.parentElement.children.length; it++) {
			if (elem.parentElement.parentElement.children[it].classList.contains("user-ad-info-id") === true) {
				lnkid = elem.parentElement.parentElement.children[it].textContent;
			}
		}

		//actionFormNewMsgForm
		fetch(window.location.href + "?oddaccount=1", {
			method: "post",
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json'
			},

			//
			body: JSON.stringify({
				Action: "admin-approvead",
				AdLnkID: lnkid,
			})
		})

		.then(response => { 
			//
			//console.log(response)
			return response.text();
		})

		.then(responsetext => {
			//
			showNotification(responsetext);
		});
	}
}


///////////////////////////
// Search
///////////////////////////

// Fetch Search Results -------------------------------------------

//	vars for later
//		important elements
let grid = document.querySelector("#content");
let body = document.querySelector("body");
let html = document.querySelector("html");
let header = document.querySelector("#header");

//		query details
let queryraw = '?s=&inc=0'; 
//console.log("Here is the raw query specified: " + queryraw);
let query = new URL(queryraw, window.location.href);

//		other stuff
let moreresults = true;
let totalgridelems = 0;

//console.log('Here is the last character of document.URL: ' + document.URL.slice(document.URL.length - 1, document.URL.length))
//console.log('Here is the query to be fetched: ' + query)

// Build and Inject HTML on Scroll ---------------------------------

//	add to increment param number for each new fetch
function incrementplus() {
	//	vars for later
	//		new query string
	let newquery = '';

	//		query string elems
	let s = '?s=';
	let exa = '&exa=';
	let dat = '&dat=';
	let tit = '&tit=';
	let aut = '&aut=';
	let url = '&url=';
	let tex = '&tex=';
	let tag = '&tag=';
	let cat = '&cat=';
	let ads = '&ads=';
	let loc = '&loc=';
	let gop = '&gop=';
	let adu = '&adu=';
	let inc = '&inc=';

	//console.log('Here is the former query: ' + query)
	//console.log('\n')
	
	//	ensure parameters exist, add values to existing strings, then add them to new query string
	if (query.searchParams.get('s') !== null) {s += query.searchParams.get('s'); newquery += s;};
	if (query.searchParams.get('exa') !== null) {exa += query.searchParams.get('exa'); newquery += exa;};
	if (query.searchParams.get('dat') !== null) {dat += query.searchParams.get('dat'); newquery += dat;};
	if (query.searchParams.get('tit') !== null) {tit += query.searchParams.get('tit'); newquery += tit;};
	if (query.searchParams.get('aut') !== null) {aut += query.searchParams.get('aut'); newquery += aut;};
	if (query.searchParams.get('url') !== null) {url += query.searchParams.get('url'); newquery += url;};
	if (query.searchParams.get('tex') !== null) {tex += query.searchParams.get('tex'); newquery += tex;};
	if (query.searchParams.get('tag') !== null) {tag += query.searchParams.get('tag'); newquery += tag;};
	if (query.searchParams.get('cat') !== null) {cat += query.searchParams.get('cat'); newquery += cat;};
	if (query.searchParams.get('ads') !== null) {ads += query.searchParams.get('ads'); newquery += ads;};
	if (query.searchParams.get('loc') !== null) {loc += query.searchParams.get('loc'); newquery += loc;};
	if (query.searchParams.get('gop') !== null) {gop += query.searchParams.get('gop'); newquery += gop;};
	if (query.searchParams.get('adu') !== null) {adu += query.searchParams.get('adu'); newquery += adu;};
	//		add 1 to the increment number here!
	if (query.searchParams.get('inc') !== null) {inc += (Number(query.searchParams.get('inc')) + 1); newquery += inc;};

	//	replace old query url with new query url
	query = new URL(newquery, window.location.href);
	
	//console.log('Here is the newly modified query: ' + query)
}

//
function loadmore() {
	//	vars for later
	let jsondata = '';

	//	Execute request
	fetch(query, {
	    method: 'GET',
	})
	.then(response => {
		jsondata = response.json(); // convert response to json
		return jsondata;
	})
	.then(jsondata => {
		//console.log("Did it work? Let's find out:")
		//console.log(jsondata);

		//	return false if last request yielded no results
		if (jsondata.length === 0) {return false}

		//	create new elements
		let gridflex1 = '<div class="side-gridflex side-grid grid-1">';
		let g1 = false;
		let gridflex2 = '<div class="side-gridflex side-gridmid grid-2">';
		let g2 = false;
		let gridflex3 = '<div class="side-gridflex side-gridbottom grid-3">';
		let g3 = false;
		let gridflex4 = '<div class="side-gridflex side-grid grid-4">';
		let g4 = false;
		let gridflex5 = '<div class="side-gridflex side-gridmid grid-5">';
		let g5 = false;
		let gridflex6 = '<div class="side-gridflex side-gridbottom grid-6">';
		let g6 = false;
		let gridflex7 = '<div class="side-gridflex side-gridbottom grid-7">';
		let g7 = false;

		for (let c = 0; c < 7; c++) {
			//	replace empty img urls
			let imgurl = '\'\'';

			if (jsondata["All"][c]["FeaturedImg"].length > 0) {
				imgurl = jsondata["All"][c]["FeaturedImg"];
			} else {
				imgurl = "/wp-content/icons/ad-backgrounds-" + (Math.floor(Math.random() * 4) + 1) + ".gif"; // choose random default background here
			}

			//	prepare urls
			let entryurl = '';

			if (jsondata["All"][c]["URL"].includes('oddgopherpage') === false && jsondata["All"][c]["URL"].includes('oddoutbound') === false) {
				//entryurl = '<p>https://www.oddnugget.com' + jsondata["All"][c]["URL"] + '</p>';
			} else if (jsondata["All"][c]["URL"].includes('oddgopherpage') === true && jsondata["All"][c]["URL"].includes('oddoutbound') === false) {
				entryurl = '<p>' + jsondata["All"][c]["URL"].replace('/oddgopherpage/', 'gopher://') + '</p>';
			}

			//if (imgurl.length !== 0) {imgurl = }

			if (c == 0 && c < jsondata["All"].length) {
				gridflex1 += '<div class="side-grid-elem side-grid-left"'+
					'style="background-image: URL('+
					imgurl+
					')">'+
					'<a href="'+	
					jsondata["All"][c]["URL"]+
					'"><h3 class="side-title">'+
					jsondata["All"][c]["Title"]+
					'</h3></a>'+entryurl+'</div>';
				g1 = true
			} else if (c == 1 && c < jsondata["All"].length) {
				gridflex2 += '<div class="side-grid-elem side-grid-right"'+
					'style="background-image: URL('+
					imgurl+
					')">'+
					'<a href="'+
					jsondata["All"][c]["URL"]+
					'"><h3 class="side-title">'+
					jsondata["All"][c]["Title"]+
					'</h3></a>'+entryurl+'</div>';
				g2 = true
			} else if (c == 2 && c < jsondata["All"].length) {
				gridflex3 += '<div class="side-grid-elem side-grid-left"'+
					'style="background-image: URL('+
					imgurl+
					')">'+
					'<a href="'+
					jsondata["All"][c]["URL"]+
					'"><h3 class="side-title">'+
					jsondata["All"][c]["Title"]+
					'</h3></a>'+entryurl+'</div>';
				g3 = true
			} else if (c == 3 && c < jsondata["All"].length) {
				gridflex4 += '<div class="side-grid-elem"'+
					'style="background-image: URL('+
					imgurl+
					')">'+
					'<a href="'+
					jsondata["All"][c]["URL"]+
					'"><h3 class="side-title">'+
					jsondata["All"][c]["Title"]+
					'</h3></a>'+entryurl+'</div>';
				g4 = true
			} else if (c == 4 && c < jsondata["All"].length) {
				gridflex5 += '<div class="side-grid-elem side-grid-right"'+
					'style="background-image: URL('+
					imgurl+
					')">'+
					'<a href="'+
					jsondata["All"][c]["URL"]+
					'"><h3 class="side-title">'+
					jsondata["All"][c]["Title"]+
					'</h3></a>'+entryurl+'</div>';
				g5 = true
			} else if (c == 5 && c < jsondata["All"].length) {
				gridflex6 += '<div class="side-grid-elem sp side-grid-right"'+
					'style="background-image: URL('+
					imgurl+
					')">'+
					'<a href="'+
					jsondata["All"][c]["URL"]+
					'"><h3 class="side-title">'+
					jsondata["All"][c]["Title"]+
					'</h3></a>'+entryurl+'</div>';
				g6 = true
			} else if (c == 6 && c < jsondata["All"].length) {
				gridflex7 += '<div class="side-grid-elem side-grid-left grid-ad"'+
					'style="background-image: URL('+
					imgurl+
					')">'+
					'<a href="'+
					jsondata["All"][c]["URL"]+
					'"><h3 class="side-title">'+
					jsondata["All"][c]["Title"]+
					'</h3></a>'+entryurl+'</div>';
				g7 = true
			}
		}

		gridflex1 += '</div>';
		gridflex2 += '</div>';
		gridflex3 += '</div>';
		gridflex4 += '</div>';
		gridflex5 += '</div>';
		gridflex6 += '</div>';
		gridflex7 += '</div>';

		//	insert new elements
		requestAnimationFrame(() => {
			if (g1 === true) {grid.innerHTML += gridflex1;}
			if (g2 === true) {grid.innerHTML += gridflex2;}
			if (g7 === true) {grid.innerHTML += gridflex7;}
			if (g4 === true) {grid.innerHTML += gridflex4;}
		});

		requestAnimationFrame(() => {
			if (g5 === true) {grid.innerHTML += gridflex5;}
			if (g6 === true) {grid.innerHTML += gridflex6;}
			if (g3 === true) {grid.innerHTML += gridflex3;}
		});
	})
}

//	run loadmore() once to start
loadmore();
incrementplus(); // modifies query to request new results next time










///////////////////////////
// Scroll Detection and Related Functionality
///////////////////////////

//
window.onscroll = () => {
	//console.log('scrolling detected!')

	//	detect scroll beyond first quarter of page
	//	~scrollY >= 1/4 of body height
	//console.log("scrollY: ", window.pageYOffset)
	if (window.pageYOffset >= offheight / 4) {
		//console.log('scrolled beyond quarter of page...')
		scrollTopBtn.classList.remove("invisible"); // handle scroll-related transforms
		//scrollTopBtn.classList.add("modifymenubtn");

		contactBtn.style.display = "none";
		privacyBtn.style.display = "none";
		mastheadBtn.style.display = "none";
		logoArea.style.display = "none";
	} else {
		scrollTopBtn.classList.add("invisible");
		//scrollTopBtn.classList.remove("modifymenubtn");

		contactBtn.style.display = "flex";
		privacyBtn.style.display = "flex";
		mastheadBtn.style.display = "flex";
		logoArea.style.display = "flex";
	}

	//	detect bottom of page
	//	(interior # of pixels of window + # of pixels scrolled vertically) >= viewable # of vertical pixels of body without margin
	if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight) {
		//console.log('bottom of page reached...')
		//	loadmore results if there are any available
		if (moreresults === true) {
			loadmore();

			if (totalgridelems < grid.childElementCount) {
				incrementplus(); // modifies query to request new results next time

				totalgridelems = grid.childElementCount;
			} else {
				moreresults = false; // stop querying server when all results are returned
			}
		}
	}
}








///////////////////////////
// Event Listeners and Related Functionality
///////////////////////////

if (actionMenu !== null) {
	//---------------Action Menu

	//------------Ads

	for (let iterat = 0; iterat < actionFormAdMenuAdContainers.length; iterat++) {
		//
		actionFormAdMenuAdContainers[iterat].addEventListener("click", showAdInfo);
	}

	for (let itery = 0; itery < actionFormAdMenuAdBackBtns.length; itery++) {
		//
		actionFormAdMenuAdBackBtns[itery].addEventListener("click", hideAdInfo);
	}

	//---

	for (let itero = 0; itero < actionFormAdMenuAdActivateBtns.length; itero++) {
		//
		actionFormAdMenuAdActivateBtns[itero].addEventListener("click", ActivateAd);
	}

	for (let iteri = 0; iteri < actionFormAdMenuAdDeactivateBtns.length; iteri++) {
		//
		actionFormAdMenuAdDeactivateBtns[iteri].addEventListener("click", DeactivateAd);
	}

	for (let itera = 0; itera < actionFormAdMenuAdUpdateBtns.length; itera++) {
		//
		actionFormAdMenuAdUpdateBtns[itera].addEventListener("click", UpdateAd);
	}

	for (let itere = 0; itere < actionFormAdMenuAdDeleteBtns.length; itere++) {
		//
		actionFormAdMenuAdDeleteBtns[itere].addEventListener("click", DeleteAd);
	}

	//-------------Chat

	actionFormInboxTit.addEventListener("click", showInbox);
	actionFormOutboxTit.addEventListener("click", showOutbox);

	//
	for (let itea = 0; itea < actionFormInboxMsgs.length; itea++) {
		//
		actionFormInboxMsgs[itea].addEventListener("click", showInboxMsg);
	}

	for (let iteb = 0; iteb < actionFormOutboxMsgs.length; iteb++) {
		//
		actionFormOutboxMsgs[iteb].addEventListener("click", showOutboxMsg);
	}

	//
	for (let ita = 0; ita < actionFormInboxBackBtns.length; ita++) {
		//
		actionFormInboxBackBtns[ita].addEventListener("click", hideInboxMsg);
	}

	for (let itb = 0; itb < actionFormOutboxBackBtns.length; itb++) {
		//
		actionFormOutboxBackBtns[itb].addEventListener("click", hideOutboxMsg);
	}

	//
	for (let itc = 0; itc < actionFormInboxReplyBtns.length; itc++) {
		//
		actionFormInboxReplyBtns[itc].addEventListener("click", navToMsgFormReply);
	}
}





	</script>

 </body>
</html>