View file watable/index.html

File size: 27.38Kb
<!DOCTYPE html>
<html>
<head>
    <title>WATable</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.js" type="text/javascript"></script>
    <script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js" type="text/javascript"></script>
    <script src="jquery.watable.js" type="text/javascript" charset="utf-8"></script>
    <link rel='stylesheet' href="http://netdna.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <link rel='stylesheet' href='watable.css'/>
    <style type="text/css">
        body { padding: 30px; font-size: 12px }
    </style>
</head>
<body>
    <h2>WATable</h2>
    <p><a href="http://wootapa-watable.appspot.com/">http://wootapa-watable.appspot.com/</a></p>
    
    <h4>Example 1. No options supplied</h4>
    <div id="example1" style="width:auto"></div>
    
    <h4>Example 2. Lots of options supplied</h4>
    <div id="example2" style="width:auto"></div>

    <script type="text/javascript">
        $(document).ready( function() {
                //First example. No options supplied.
                $('#example1').WATable({
                    data: generateSampleData(2, true)
                });
                
                //Second example that shows all options.
                var waTable = $('#example2').WATable({
                //data: generateSampleData(100), //Initiate with data if you already have it
                debug:false,                //Prints some debug info to console
                dataBind: true,             //Auto-updates table when changing data row values. See example below. (Note. You need a column with the 'unique' property)
                pageSize: 8,                //Initial pagesize
                pageSizePadding: true,      //Pads with empty rows when pagesize is not met
                //transition: 'slide',       //Type of transition when paging (bounce, fade, flip, rotate, scroll, slide).Requires https://github.com/daneden/animate.css.
                //transitionDuration: 0.2,    //Duration of transition in seconds.
                filter: true,               //Show filter fields
                sorting: true,              //Enable sorting
                sortEmptyLast:true,         //Empty values will be shown last
                columnPicker: true,         //Show the columnPicker button
                pageSizes: [1,5,8,12,200],  //Set custom pageSizes. Leave empty array to hide button.
                hidePagerOnEmpty: true,     //Removes the pager if data is empty.
                checkboxes: true,           //Make rows checkable. (Note. You need a column with the 'unique' property)
                checkAllToggle:true,        //Show the check-all toggle
                preFill: true,              //Initially fills the table with empty rows (as many as the pagesize).
                //url: '/someWebservice'    //Url to a webservice if not setting data manually as we do in this example
                //urlData: { report:1 }     //Any data you need to pass to the webservice
                //urlPost: true             //Use POST httpmethod to webservice. Default is GET.
                types: {                    //If you want, you can supply some properties that will be applied for specific data types.
                    string: {
                        //filterTooltip: "Giggedi..."    //What to say in tooltip when hoovering filter fields. Set false to remove.
                        //placeHolder: "Type here..."    //What to say in placeholder filter fields. Set false for empty.
                    },
                    number: {
                        decimals: 1   //Sets decimal precision for float types
                    },
                    bool: {
                        //filterTooltip: false
                    },
                    date: {
                      utc: true,            //Show time as universal time, ie without timezones.
                      //format: 'yy/dd/MM',   //The format. See all possible formats here http://arshaw.com/xdate/#Formatting.
                      datePicker: true      //Requires "Datepicker for Bootstrap" plugin (http://www.eyecon.ro/bootstrap-datepicker).
                    }
                },
                actions: {                //This generates a button where you can add elements.
                    filter: true,         //If true, the filter fields can be toggled visible and hidden.
                    columnPicker: true,   //if true, the columnPicker can be toggled visible and hidden.
                    custom: [             //Add any other elements here. Here is a refresh and export example.
                      $('<a href="#" class="refresh"><span class="glyphicon glyphicon-refresh"></span>&nbsp;Refresh</a>'),
                      $('<a href="#" class="export all"><span class="glyphicon glyphicon-share"></span>&nbsp;Export all rows</a>'),
                      $('<a href="#" class="export checked"><span class="glyphicon glyphicon-share"></span>&nbsp;Export checked rows</a>'),
                      $('<a href="#" class="export filtered"><span class="glyphicon glyphicon-share"></span>&nbsp;Export filtered rows</a>'),
                      $('<a href="#" class="export rendered"><span class="glyphicon glyphicon-share"></span>&nbsp;Export rendered rows</a>')
                    ]
                },
                tableCreated: function(data) {    //Fires when the table is created / recreated. Use it if you want to manipulate the table in any way.
                    console.log('table created'); //data.table holds the html table element.
                    console.log(data);            //'this' keyword also holds the html table element.
                },
                rowClicked: function(data) {      //Fires when a row or anything within is clicked (Note. You need a column with the 'unique' property).
                    console.log('row clicked');   //data.event holds the original jQuery event.
                                                  //data.row holds the underlying row you supplied.
                                                  //data.index holds the index of row in rows array (Useful when you want to remove the row)
                                                  //data.column holds the underlying column you supplied.
                                                  //data.checked is true if row is checked. (Set to false/true to have it unchecked/checked)
                                                  //'this' keyword holds the clicked element.

                    //Removes the row if user clicked on the column called 'remove'.
                    if (data.column.column == "remove") {
                        data.event.preventDefault();
                        //Remove fast with dataBind option
                        waTable.getData().rows.splice(data.index, 1);
                        Platform.performMicrotaskCheckpoint();

                        //This would have worked fine as well, but is slower
                        //var d = waTable.getData();
                        //d.rows.splice(data.index, 1);
                        //waTable.setData(d);
                    }
                    //We can look at classes on the clicked element as well
                    if (this.classList.contains('someClass')) {
                        //Do something...
                    }
                    //Example toggle checked state
                    if (data.column.column == "check") {
                        data.checked = !data.checked;
                    }
                    console.log(data);
                },
                columnClicked: function(data) {    //Fires when a column is clicked
                  console.log('column clicked');  //data.event holds the original jQuery event
                  console.log(data);              //data.column holds the underlying column you supplied
                                                  //data.descending is true when sorted descending (duh)
                },
                pageChanged: function(data) {      //Fires when manually changing page
                  console.log('page changed');    //data.event holds the original jQuery event
                  console.log(data);              //data.page holds the new page index
                },
                pageSizeChanged: function(data) {  //Fires when manually changing pagesize
                  console.log('pagesize changed');//data.event holds teh original event
                  console.log(data);              //data.pageSize holds the new pagesize
                }
            }).data('WATable');  //This step reaches into the html data property to get the actual WATable object. Important if you want a reference to it as we want here.

            //Generate some data
            var data = generateSampleData(500);
            waTable.setData(data);  //Sets the data.
            //waTable.setData(data, true); //Sets the data but prevents any previously set columns from being overwritten
            //waTable.setData(data, false, false); //Sets the data and prevents any previously checked rows from being reset

            //Get the data
            var allRows = waTable.getData(false); //Returns the data you previously set.
            var checkedRows = waTable.getData(true); //Returns only the checked rows.
            var filteredRows = waTable.getData(false, true); //Returns only the filtered rows.
            var renderedRows = waTable.getData(false, false, true) //Returns only the rendered rows.

            //Set options on the fly
            var pageSize = waTable.option("pageSize"); //Get option
            //waTable.option("pageSize", pageSize); //Set option

            //Databinding example
            var row = waTable.getRow(5).row; //Get row with unique value of 5.
            row.name = "Data-Binding Works"; //This would update the table...but only in ultra modern browsers. (See here http://caniuse.com/#search=observe)
            Platform.performMicrotaskCheckpoint(); //This make sure it also works in browsers not yet compatible with Object.observe. This is the polyfill that's used.(https://github.com/polymer/observe-js).

            //More databinding
            data.rows.shift(); //Removes the first row.
            var newRow = generateSampleData(1).rows[0];
            data.rows.push(newRow); //Add new row
            Platform.performMicrotaskCheckpoint();

            //Example event handler triggered by the custom refresh link above.
            $('#example2').on('click', '.refresh', function(e) {
                e.preventDefault();
                //Get and set some new data
                var data = generateSampleData(100);
                waTable.setData(data, true);
            });
            //Example event handler triggered by the custom export links above.
            $('#example2').on('click', '.export', function(e) {
                e.preventDefault();
                var elem = $(e.target);
                var data;
                if (elem.hasClass('all')) data = waTable.getData(false);
                else if (elem.hasClass('checked')) data = waTable.getData(true);
                else if (elem.hasClass('filtered')) data = waTable.getData(false, true);
                else if (elem.hasClass('rendered')) data = waTable.getData(false, false, true);
                console.log(data.rows.length + ' rows returned', data);
                alert(data.rows.length + ' rows returned.\nSee data in console.');
            });

        });

        //Generates some data.
        function generateSampleData(limit, simpleMode) {

            //First define the columns
            var cols = {
                userId: {
                    index: 1, //The order this column should appear in the table
                    type: "number", //The type. Possible are string, number, bool, date(in milliseconds).
                    friendly: "<span class='glyphicon glyphicon-user'></span>",  //Name that will be used in header. Can also be any html as shown here.
                    format: "<a href='#' target='_blank'>{0}</a>",  //Used to format the data anything you want. Use {0} as placeholder for the actual data.
                    unique: true,  //This is required if you want checkable rows, databinding or to use the rowClicked callback. Be certain the values are really unique or weird things will happen.
                    sortOrder: "asc", //Data will initially be sorted by this column. Possible are "asc" or "desc"
                    tooltip: "This column has an initial filter", //Show some additional info about column
                    filter: "1..400" //Set initial filter.
                },
                name: {
                    index: 2,
                    type: "string",
                    friendly: "Name",
                    cls: "blue, anotherClass", //apply some css classes
                    tooltip: "This column has a custom placeholder and css classes", //Show some additional info about column
                    placeHolder: "abc123" //Overrides default placeholder and placeholder specified in data types(row 34).
                },
                age: {
                    index: 3,
                    type: "number",
                    friendly: "Age",
                    sorting: true, //dont allow sorting
                    tooltip: "This column has filtering and sorting turned off", //Show some additional info about column
                    filter: false //Removes filter field for this column
                },
                weight: {
                    index: 4,
                    type: "number",
                    decimals: 2, //Force decimal precision
                    friendly: "Weight",
                    placeHolder: "50..90",
                    format: "{0}kg",
                    tooltip: "This column has no tooltip for the filter", //Show some additional info about column
                    filterTooltip: false //Turn off tooltip for this column
                },
                height: {
                    index: 5,
                    type: "number",
                    friendly: "Height",
                    hidden: true //Hides the column. Useful if you want this value later on but not visible to user. It can be made visible if columnPicker is enabled.
                },
                important: {
                    index: 6,
                    type: "bool",
                    friendly: "Important"
                },
                someDate: {
                    index: 7,
                    type: "date", //Don't forget dates are expressed in milliseconds.
                    friendly: "SomeDate"
                },
                someDateDay: {
                    index: 8,
                    type: "date", //Don't forget dates are expressed in milliseconds
                    dateFormat: "dddd", //Special date format. See all possible formats here http://arshaw.com/xdate/#Formatting.
                    friendly: "Day"
                },
                remove: {
                    index: 9,
                    type: "string",
                    friendly: "<span class='glyphicon glyphicon-remove'></span>",
                    format: "<a href='#' title='Remove me'><span class='glyphicon glyphicon-remove'></span></a>",
                    filter: false,
                    sorting: false,
                    hidden: simpleMode //For the sake of this demo, this column gets hidden for example1
                },
                check: {
                    index: 10,
                    type: "string",
                    friendly: "<span class='glyphicon glyphicon-check'></span>",
                    format: "<a href='#' title='Toggle checked'><span class='glyphicon glyphicon-check'></span></a>",
                    filter: false,
                    sorting: false,
                    hidden: simpleMode //For the sake of this demo, this column gets hidden for example1
                }
            };

            /*
              Create the rows (This step is of course normally done by your web server). 
              What's worth mentioning is the special row properties. See some examples below.
              <column>Format allows you to override column format and have it formatted the way you want.
              <column>Cls allows you to add css classes on the cell(td) element.
              row-checkable allows you to prevent rows from being checkable.
              row-checked allows you to pre-check a row.
              row-cls allows you to add css classes to the row(tr) element.
            */
            var rows = [];
            var i = 1;
            while(i <= limit)
            {
                //We leave some fields intentionally undefined, so you can see how sorting/filtering works with these.
                var row = {};
                row.userId           = i;
                row.name             = i % 100 == 0 ? undefined : elfName(); //Random name
                row.age              = Math.floor(Math.random() * 50) + 20; //Random age
                row.ageFormat        = row.age + (row.age > 50 ? " (senior)" : " (junior)"); //Special formatting
                row.weight           = (Math.floor(Math.random() * 40) + 50) + (Math.floor(Math.random() * 100) / 100); //Random weight
                row.weightCls        = row.weight < 70 ? 'green' : row.weight < 80 && row.weight >= 70 ? 'yellow' : 'red'; //Add css class to cell
                row.height           = Math.floor(Math.random() * 50) + 150; //Random height
                row.important        = i % 5 == 0 ? 1 : 0; //Random important
                row.someDate         = i % 4 == 0 ? undefined : Date.now() + (i*Math.floor(Math.random()*(60 * 60 * 24 * 100))); //Random date
                row.someDateDay      = i % 4 == 0 ? "" : row.someDate; //Use same date as above, but its column has different formatting
                row["row-checkable"] = i % 4 != 0; //disable checking for every 4th row
                row["row-checked"]   = i % 3 == 0; //pre check every 3rd row
                row["row-cls"]       = i % 3 == 0 ? "gray, anotherClass" : ""; //apply some row css classes for every 3rd row
                
                row.secret           = { "secret" : "foobar" }; //Add something else that you want later(ex in rowClicked event)

                rows.push(row);
                i++;
            }

            //Create the returning object. Besides cols and rows, you can also pass any other object you would need later on.
            var data = {
                cols: cols,
                rows: rows,
                otherStuff: {
                    thatIMight: 1,
                    needLater: true
                }
            };
            return data;
        }

        //Helper function to generate names. Ignore this.
        function elfName() {
            var elf_male = new Array("Abardon", "Acaman", "Achard", "Ackmard", "Agon", "Agnar", "Abdun", "Aidan", "Airis", "Aldaren", "Alderman", "Alkirk", "Amerdan", "Anfarc", "Aslan", "Actar", "Atgur", "Atlin", "Aldan", "Badek", "Baduk", "Bedic", "Beeron", "Bein", "Bithon", "Bohl", "Boldel", "Bolrock", "Bredin", "Bredock", "Breen", "tristan", "Bydern", "Cainon", "Calden", "Camon", "Cardon", "Casdon", "Celthric", "Cevelt", "Chamon", "Chidak", "Cibrock", "Cipyar", "Colthan", "Connell", "Cordale", "Cos", "Cyton", "Daburn", "Dawood", "Dak", "Dakamon", "Darkboon", "Dark", "Darg", "Darmor", "Darpick", "Dask", "Deathmar", "Derik", "Dismer", "Dokohan", "Doran", "Dorn", "Dosman", "Draghone", "Drit", "Driz", "Drophar", "Durmark", "Dusaro", "Eckard", "Efar", "Egmardern", "Elvar", "Elmut", "Eli", "Elik", "Elson", "Elthin", "Elbane", "Eldor", "Elidin", "Eloon", "Enro", "Erik", "Erim", "Eritai", "Escariet", "Espardo", "Etar", "Eldar", "Elthen", "Elfdorn", "Etran", "Eythil", "Fearlock", "Fenrirr", "Fildon", "Firdorn", "Florian", "Folmer", "Fronar", "Fydar", "Gai", "Galin", "Galiron", "Gametris", "Gauthus", "Gehardt", "Gemedes", "Gefirr", "Gibolt", "Geth", "Gom", "Gosform", "Gothar", "Gothor", "Greste", "Grim", "Gryni", "Gundir", "Gustov", "Halmar", "Haston", "Hectar", "Hecton", "Helmon", "Hermedes", "Hezaq", "Hildar", "Idon", "Ieli", "Ipdorn", "Ibfist", "Iroldak", "Ixen", "Ixil", "Izic", "Jamik", "Jethol", "Jihb", "Jibar", "Jhin", "Julthor", "Justahl", "Kafar", "Kaldar", "Kelar", "Keran", "Kib", "Kilden", "Kilbas", "Kildar", "Kimdar", "Kilder", "Koldof", "Kylrad", "Lackus", "Lacspor", "Lahorn", "Laracal", "Ledal", "Leith", "Lalfar", "Lerin", "Letor", "Lidorn", "Lich", "Loban", "Lox", "Ludok", "Ladok", "Lupin", "Lurd", "Mardin", "Markard", "Merklin", "Mathar", "Meldin", "Merdon", "Meridan", "Mezo", "Migorn", "Milen", "Mitar", "Modric", "Modum", "Madon", "Mafur", "Mujardin", "Mylo", "Mythik", "Nalfar", "Nadorn", "Naphazw", "Neowald", "Nildale", "Nizel", "Nilex", "Niktohal", "Niro", "Nothar", "Nathon", "Nadale", "Nythil", "Ozhar", "Oceloth", "Odeir", "Ohmar", "Orin", "Oxpar", "Othelen", "Padan", "Palid", "Palpur", "Peitar", "Pendus", "Penduhl", "Pildoor", "Puthor", "Phar", "Phalloz", "Qidan", "Quid", "Qupar", "Randar", "Raydan", "Reaper", "Relboron", "Riandur", "Rikar", "Rismak", "Riss", "Ritic", "Ryodan", "Rysdan", "Rythen", "Rythorn", "Sabalz", "Sadaron", "Safize", "Samon", "Samot", "Secor", "Sedar", "Senic", "Santhil", "Sermak", "Seryth", "Seth", "Shane", "Shard", "Shardo", "Shillen", "Silco", "Sildo", "Silpal", "Sithik", "Soderman", "Sothale", "Staph", "Suktar", "zuth", "Sutlin", "Syr", "Syth", "Sythril", "Talberon", "Telpur", "Temil", "Tamilfist", "Tempist", "Teslanar", "Tespan", "Tesio", "Thiltran", "Tholan", "Tibers", "Tibolt", "Thol", "Tildor", "Tilthan", "Tobaz", "Todal", "Tothale", "Touck", "Tok", "Tuscan", "Tusdar", "Tyden", "Uerthe", "Uhmar", "Uhrd", "Updar", "Uther", "Vacon", "Valker", "Valyn", "Vectomon", "Veldar", "Velpar", "Vethelot", "Vildher", "Vigoth", "Vilan", "Vildar", "Vi", "Vinkol", "Virdo", "Voltain", "Wanar", "Wekmar", "Weshin", "Witfar", "Wrathran", "Waytel", "Wathmon", "Wider", "Wyeth", "Xandar", "Xavor", "Xenil", "Xelx", "Xithyl", "Yerpal", "Yesirn", "Ylzik", "Zak", "Zek", "Zerin", "Zestor", "Zidar", "Zigmal", "Zilex", "Zilz", "Zio", "Zotar", "Zutar", "Zytan");
            var elf_female = new Array("Acele Acholate", "Ada", "Adiannon", "Adorra", "Ahanna", "Akara", "Akassa", "Akia", "Amara", "Amarisa", "Amarizi", "Ana", "Andonna", "Ariannona", "Arina", "Arryn", "Asada", "Awnia", "Ayne", "Basete", "Bathelie", "Bethel", "Brana", "Brynhilde", "Calene", "Calina", "Celestine", "Corda", "Enaldie", "Enoka", "Enoona", "Errinaya", "Fayne", "Frederika", "Frida", "Gvene", "Gwethana", "Helenia", "Hildandi", "Helvetica", "Idona", "Irina", "Irene", "Illia", "Irona", "Justalyne", "Kassina", "Kilia", "Kressara", "Laela", "Laenaya", "Lelani", "Luna", "Linyah", "Lyna", "Lynessa", "Mehande", "Melisande", "Midiga", "Mirayam", "Mylene", "Naria", "Narisa", "Nelena", "Nimaya", "Nymia", "Ochala", "Olivia", "Onathe", "Parthinia", "Philadona", "Prisane", "Rhyna", "Rivatha", "Ryiah", "Sanata", "Sathe", "Senira", "Sennetta", "Serane", "Sevestra", "Sidara", "Sidathe", "Sina", "Sunete", "Synestra", "Sythini", "zena", "Tabithi", "Tomara", "Teressa", "Tonica", "Thea", "Teressa", "Urda", "Usara", "Useli", "Unessa", "ursula", "Venessa", "Wanera", "Wellisa", "yeta", "Ysane", "Yve", "Yviene", "Zana", "Zathe", "Zecele", "Zenobe", "Zema", "Zestia", "Zilka", "Zoucka", "Zona", "Zyneste", "Zynoa");
            var elf_surname = new Array("Abardon", "Acaman", "Achard", "Ackmard", "Agon", "Agnar", "Aldan", "Abdun", "Aidan", "Airis", "Aldaren", "Alderman", "Alkirk", "Amerdan", "Anfarc", "Aslan", "Actar", "Atgur", "Atlin", "Badek", "Baduk", "Bedic", "Beeron", "Bein", "Bithon", "Bohl", "Boldel", "Bolrock", "Bredin", "Bredock", "Breen", "tristan", "Bydern", "Cainon", "Calden", "Camon", "Cardon", "Casdon", "Celthric", "Cevelt", "Chamon", "Chidak", "Cibrock", "Cipyar", "Colthan", "Connell", "Cordale", "Cos", "Cyton", "Daburn", "Dawood", "Dak", "Dakamon", "Darkboon", "Dark", "Dark", "Darmor", "Darpick", "Dask", "Deathmar", "Derik", "Dismer", "Dokohan", "Doran", "Dorn", "Dosman", "Draghone", "Drit", "Driz", "Drophar", "Durmark", "Dusaro", "Eckard", "Efar", "Egmardern", "Elvar", "Elmut", "Eli", "Elik", "Elson", "Elthin", "Elbane", "Eldor", "Elidin", "Eloon", "Enro", "Erik", "Erim", "Eritai", "Escariet", "Espardo", "Etar", "Eldar", "Elthen", "Etran", "Eythil", "Fearlock", "Fenrirr", "Fildon", "Firdorn", "Florian", "Folmer", "Fronar", "Fydar", "Gai", "Galin", "Galiron", "Gametris", "Gauthus", "Gehardt", "Gemedes", "Gefirr", "Gibolt", "Geth", "Gom", "Gosform", "Gothar", "Gothor", "Greste", "Grim", "Gryni", "Gundir", "Gustov", "Halmar", "Haston", "Hectar", "Hecton", "Helmon", "Hermedes", "Hezaq", "Hildar", "Idon", "Ieli", "Ipdorn", "Ibfist", "Iroldak", "Ixen", "Ixil", "Izic", "Jamik", "Jethol", "Jihb", "Jibar", "Jhin", "Julthor", "Justahl", "Kafar", "Kaldar", "Kelar", "Keran", "Kib", "Kilden", "Kilbas", "Kildar", "Kimdar", "Kilder", "Koldof", "Kylrad", "Lackus", "Lacspor", "Lahorn", "Laracal", "Ledal", "Leith", "Lalfar", "Lerin", "Letor", "Lidorn", "Lich", "Loban", "Lox", "Ludok", "Ladok", "Lupin", "Lurd", "Mardin", "Markard", "Merklin", "Mathar", "Meldin", "Merdon", "Meridan", "Mezo", "Migorn", "Milen", "Mitar", "Modric", "Modum", "Madon", "Mafur", "Mujardin", "Mylo", "Mythik", "Nalfar", "Nadorn", "Naphazw", "Neowald", "Nildale", "Nizel", "Nilex", "Niktohal", "Niro", "Nothar", "Nathon", "Nadale", "Nythil", "Ozhar", "Oceloth", "Odeir", "Ohmar", "Orin", "Oxpar", "Othelen", "Padan", "Palid", "Palpur", "Peitar", "Pendus", "Penduhl", "Pildoor", "Puthor", "Phar", "Phalloz", "Qidan", "Quid", "Qupar", "Randar", "Raydan", "Reaper", "Relboron", "Riandur", "Rikar", "Rismak", "Riss", "Ritic", "Ryodan", "Rysdan", "Rythen", "Rythorn", "Sabalz", "Sadaron", "Safize", "Samon", "Samot", "Secor", "Sedar", "Senic", "Santhil", "Sermak", "Seryth", "Seth", "Shane", "Shard", "Shardo", "Shillen", "Silco", "Sildo", "Silpal", "Sithik", "Soderman", "Sothale", "Staph", "Suktar", "zuth", "Sutlin", "Syr", "Syth", "Sythril", "Talberon", "Telpur", "Temil", "Tamilfist", "Tempist", "Teslanar", "Tespan", "Tesio", "Thiltran", "Tholan", "Tibers", "Tibolt", "Thol", "Tildor", "Tilthan", "Tobaz", "Todal", "Tothale", "Touck", "Tok", "Tuscan", "Tusdar", "Tyden", "Uerthe", "Uhmar", "Uhrd", "Updar", "Uther", "Vacon", "Valker", "Valyn", "Vectomon", "Veldar", "Velpar", "Vethelot", "Vildher", "Vigoth", "Vilan", "Vildar", "Vi", "Vinkol", "Virdo", "Voltain", "Wanar", "Wekmar", "Weshin", "Witfar", "Wrathran", "Waytel", "Wathmon", "Wider", "Wyeth", "Xandar", "Xavor", "Xenil", "Xelx", "Xithyl", "Yerpal", "Yesirn", "Ylzik", "Zak", "Zek", "Zerin", "Zestor", "Zidar", "Zigmal", "Zilex", "Zilz", "Zio", "Zotar", "Zutar", "Zytan");
            var prefix_male = elf_male;
            var prefix_female = elf_female;
            var suffix = elf_surname;
            var n1m = parseInt(Math.random() * prefix_male.length);
            var n1f = parseInt(Math.random() * prefix_female.length);
            var n2 = parseInt(Math.random() * suffix.length);
            var n2ekstra = parseInt(Math.random() * suffix.length);
            var extraname = "extranahme";
            var prename_male = prefix_male[n1m].slice(0, 1).toUpperCase() + prefix_male[n1m].slice(1);
            var prename_female = prefix_female[n1f].slice(0, 1).toUpperCase() + prefix_female[n1f].slice(1);
            var sufname = suffix[n2].slice(0, 1).toUpperCase() + suffix[n2].slice(1);
            var extraname = suffix[n2ekstra].slice(0, 1).toUpperCase() + suffix[n2ekstra].slice(1);
            var n3 = parseInt(Math.random() * 100);
            if (n3 <= 40) {
                name = prename_male + " " + sufname
            } else if (n3 > 40 && n3 <= 70) {
                name = prename_female + " " + sufname
            }
            return name;
        }
</script>
</body>
</html>