Login   Register  
PHP Classes
elePHPant
Icontem

File: setmenu/setmenu.js

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of MarPlo  >  Online PHP Menu Builder Class  >  setmenu/setmenu.js  >  Download  
File: setmenu/setmenu.js
Role: Auxiliary data
Content type: text/plain
Description: JavaScript code to create the menu
Class: Online PHP Menu Builder Class
Create hierarchic menus stored in a MySQL database
Author: By
Last change: Fixed bugs related to special characters
Date: 2013-05-07 23:28
Size: 19,874 bytes
 

Contents

Class file image Download
// Multi-Level System Script - http://coursesweb.net/

// Class to create multiple dropdown <select> lists
var MakeSLists = function() {
  // messages displayed
  var lang = {
    'erraddnct': 'Add a name in text field',
    'errchg0': 'Root cannot be changed.',
    'errm_name': 'Add a name for resource, between 2 and 250 characters.\n Only Letters, Numbers, "-", and "_"',
    'dchanged':'Data changed',
    'delitem': 'The selected List and its sub-categories succesfuly deleted'
  }
  var thisob = this;        // stores the 'this' reference of the object with this class

  var geto = 'txt';         // if 'mysql' value, gets data from MySQL database
  var saveto = 'txt';       // to tell php where to save data
  var ctgItems = {'0':[]};          // stores items with 'ctg_id'/option:[id_sub-categories] for each <option> in <select> (starts with 'root')
  var ctgData = {'0':{'namec':'Root', 'lurl':'#', 'ctg':':'}};

  var opt1 = 0;       // to know when is selected `1st option in <select>, 1 (modified in addSubSelect(), used in addCategory())
  var ctparent = ':';       // the value for 'ctg' column
  var ctid = 0;             // id of category /sub-category
  var sid = 'sl';           // the id first <select> (Root). Will contain the id of last/current <select>

/** Functions to set <select> data **/

  // empty text field for category name, and resets link url
  var resetNameUrl = function() {
    document.getElementById('namec').value = '';
    document.getElementById('lurl').value = '#';
  }

  // adds category /sub-category in select-lists
  function addCategory() {
    var namec = document.getElementById('namec').value.replace(/\</g, '&lt;').replace(/\>/g, '&gt;').replace(/"/g, '&quot;');    // option value (replace <>" with their html-encodes)
    var lurl = encodeURI(document.getElementById('lurl').value).replace(/\</g, '&lt;').replace(/\>/g, '&gt;').replace(/"/g, '&quot;');    // get link address

    if(namec.length > 0) {
      // adds it in $ctgData. Gets the last-index, to set /add id of new category
      var idct = 0;
      for(var ix in ctgData) {
        if((ix * 1) > idct) idct = ix * 1;
      }
      idct++;

      // the level-category in this sub-category
      if(ctid > 0) var setctg = ctparent+ctid+':';
      else var setctg = ctparent;
      ctgData[idct] = {'namec':namec, 'lurl':lurl, 'ctg':setctg};

      // if parent-category exists in $ctgItems, adds it in array, else, create the parent-category array
      if(ctgItems[ctid]) ctgItems[ctid].push(idct);
      else ctgItems[ctid] = [idct];

      // sets the id of <select> which is displayed with the new category (current select id if it is added in the same select, $opt1 indicates the selection is current <select>)
      var sid_next = (opt1 == 1) ? sid : sid+'_n';

      // sets the ID of tag in which adds the <select> (current-parent tag if it was selected 1st <option>)
      var idadds = (opt1 == 1 && document.getElementById('n_'+sid)) ? document.getElementById('n_'+sid).parentNode.parentNode.id : 'n_'+sid;

      // adds the <select> with <option>s and tag for next sub-<select>
      if(ctgItems[ctid].length > 0) document.getElementById(idadds).innerHTML = getSelect(ctgItems[ctid], sid_next);

      resetNameUrl();          // empty category-name, reset link url
      document.getElementById('curentitem').innerHTML = ctgData[ctid].namec;    // display curent selected item
      document.getElementById('m_menu').innerHTML = setHtml();    // display html code
    }
    else {
      // focus text field, and message
      document.getElementById('namec').focus();
      alert(lang.erraddnct);
    }
  }

  // modify the name of category/sub-category in last selected <option>
  function modifyCategory() {
    var namec = document.getElementById('namec').value.replace(/\</g, '&lt;').replace(/\>/g, '&gt;').replace(/"/g, '&quot;');    // option value (replace <>" with their html-encodes)
    var lurl = encodeURI(document.getElementById('lurl').value).replace(/\</g, '&lt;').replace(/\>/g, '&gt;').replace(/"/g, '&quot;');    // gets link address

    // if not root
    if(ctid != 0) {
      // change the name and link in ctgData, to the id of category
      ctgData[ctid].namec = namec;
      ctgData[ctid].lurl = lurl;
      var parentid = getParentId(ctid);   // gets parent-ID to pas its array with sub-categories to getSelect()
      ctid = parentid;       // sets current-id to parentid couse refreshes current <select>
      opt1 = 1;     // to know it is on 1st option in <select>

      // re-adds the <select> with <option>s, in the <span> with current <select>
      var parentSpan = sid.replace(/_n$/i, '') ? sid.replace(/_n$/i, '') : sid;        // span id of current <select>
      if(ctgItems[parentid].length > 0) document.getElementById('n_'+parentSpan).innerHTML = getSelect(ctgItems[parentid], sid);

      resetNameUrl();          // empty category-name, reset link url
      document.getElementById('m_menu').innerHTML = setHtml();    // display html code

      document.getElementById('curentitem').innerHTML = ctgData[ctid].namec;    // display curent selected item
      alert(lang.dchanged);
    }
    else alert(lang.errchg0);
  }

  // delete the category in last selected <option> (including all its sub-categories), delete also its id in array of its parent in $ctgItems
  function deleteCategory() {
    // if not root
    if(ctid != 0) {
      delete ctgData[ctid];
      delete ctgItems[ctid];
      var parentid = getParentId(ctid);   // gets parent-ID

      // traverses the items in parent to remove deleted item
      var remainctg = [];          // stores the remaining items, to be added in parent
      for(var i in ctgItems[parentid]) {
        if(ctgItems[parentid][i] != ctid) remainctg.push(ctgItems[parentid][i]);
      }
      ctgItems[parentid] = remainctg;

      addSelCtgs();      // resets data and adds 1st <select> list with main categories
      resetNameUrl();          // empty category-name, reset link url

      document.getElementById('curentitem').innerHTML = ctgData[0].namec;    // display curent selected item
      alert(lang.delitem);
    }
    else alert(lang.errchg0);
  }

  // returns the ID of parent sub-category (idsct)
  var getParentId = function(idsct) {
    var parentid = 0;
    var breakl = 0;
    // traverses the array of each item in $ctgItems, if find idsct, stores to return it, stop the loop
    for(var idpr in ctgItems) {
      var nrarsubctg = ctgItems[idpr].length;
      for(var i=0; i<nrarsubctg; i++) {
        if(ctgItems[idpr][i] == idsct) {
          parentid = idpr;
          breakl = 1;
        }
        if(breakl == 1) break;
      }
    }
    return parentid * 1;
  }

  // resets data and adds 1st <select> with main categories
  function addSelCtgs() {
    // reset these properties couse after delete it is displayed 1st list
    ctid = 0;
    sid = 'sl';
    ctparent = ':';

    // if items in Root, shows 1st <select>, else, resets properties to initial value
    if(ctgItems[0].length > 0) document.getElementById('n_'+sid).innerHTML = getSelect(ctgItems[0], sid+'_n');
    else {
      ctgItems = {'0':[]};
      ctgData = {'0':{'namec':'Root', 'lurl':'#', 'ctg':':'}};
      document.getElementById('n_'+sid).innerHTML = '';
    }

    document.getElementById('m_menu').innerHTML = setHtml();    // display html code
  }

  // return <select> list with category-IDs in arsubctg array in $ctgItems, receives the array, and the ID for <select>
  var getSelect = function(arsubctg, ids) {
    // gets the level of current list
    var levelnr = ids.split('_').length - 1;
    var slist = '<div><div><sub>Level '+ levelnr +'</sub><select onchange="obMSL.addSubSelect(this)" id="'+ids+'" name="'+ids+'"><option value="'+ctid+'_'+ctparent+'_">---</option>';
    var nrarsubctg = arsubctg.length

    // traverse the object and create <option> with value=idctg_level
    for(var i in arsubctg) {
      if(ctgData[arsubctg[i]]) slist += '<option value="'+arsubctg[i]+'_'+ctgData[arsubctg[i]].ctg+'">'+ctgData[arsubctg[i]].namec+'</option>';
    }

    return slist+'</select></div><span id="n_'+ids+'"></span></div>';
  }

  // function to get the dropdown list, receives the selected list object
  this.addSubSelect = function(slist) {
    sid = slist.id;         // store the id of selected list in sid property
    var opid_lvl = slist.value.split('_');      // separes id and parent-category of selected category /option
    ctid = opid_lvl[0] * 1;           // id of selected category
    ctparent = opid_lvl[1];           // stores the parent-category

    document.getElementById('n_'+sid).innerHTML = '';       // empty the tag in which will be added the <select>

    // if selected option is 1st <option> (value ends with '_'), empty the tag for next-select
    if(slist.value.match(/_$/)) opt1 = 1;       // to know it was 1st <option>
    else  opt1 = 0;       // to know isn't 1st <option>

    // if exists object (with item) of the selected option in $ctgItems adds the <select> with <option>s and tag for next sub-<select>
    // else, empty the tag in which is added the sub-<select> of this <select>
    if(opt1 == 0 && ctgItems[ctid] && ctgItems[ctid].length > 0) {
      document.getElementById('n_'+sid).innerHTML = getSelect(ctgItems[ctid], sid+'_n');
    }
    else document.getElementById('n_'+sid).innerHTML = '';

    // if not 1st <option> and ctgData item, adds its Name and URL in text field, else, empty those fields
    if(opt1 == 0 && ctgData[ctid]) {
      document.getElementById('namec').value = ctgData[ctid].namec.replace(/&lt;/ig, '<').replace(/&gt;/ig, '>').replace(/&quot;/ig, '"');
      document.getElementById('lurl').value = decodeURI(ctgData[ctid].lurl.replace(/&lt;/ig, '<').replace(/&gt;/ig, '>'));
    }
    else resetNameUrl();

    document.getElementById('curentitem').innerHTML = ctgData[ctid].namec;    // display curent selected item
  }

/** Get-Codes functions **/

  // adds in #m_menu and #htmlcode textarea the html code of data procesed from $ctgItems and $ctgData
  var setHtml = function() {
    document.getElementById('m_menu').innerHTML = '';    // to have empty the tag in which adds the html code

    // traverses $ctgItems to add each item in html tags
    for(var i in ctgItems) {
      var addcode = '<ul>';     // stores <li>s with categories of each direct item in $ctgItems
      var nrctgi = ctgItems[i].length;       // number of categories in each item

      // traverses the array with categories in each item, and adds them in tags, with their name from $ctgData
      for(var i2=0; i2<nrctgi; i2++) {
        var clsli = ctgItems[ctgItems[i][i2]] ? ' class="litems"' : '';       // add class to items with childs
        addcode += '<li id="ctg'+ctgItems[i][i2]+'"><a href="'+ ctgData[ctgItems[i][i2]].lurl +'" title="'+ ctgData[ctgItems[i][i2]].namec +'"'+ clsli +'>'+ ctgData[ctgItems[i][i2]].namec +'</a></li>';
      }

      // closes the html tag, and appends the code in its coresponding category
      addcode += '</ul>';
      var idul = (i == 0) ? 'm_menu' : 'ctg'+i;      // id of current defined <ul>
      if(document.getElementById(idul)) document.getElementById(idul).innerHTML += addcode;
    }

     return document.getElementById('m_menu').innerHTML.replace(/ id="ctg[0-9]+"/ig, '');     // returns html code, deleting the IDs
  }

  // returns the string with JSON code of objects $ctgItems and $ctgData
  var setJsonStr = function() {
    return '['+ JSON.stringify(ctgItems) +',\n'+ JSON.stringify(ctgData) +']';
  }

  // adds in #sqlcode textarea the SQL code that can be used to store $ctgData in SQL database
  var setSql = function() {
    var addcode = 'CREATE TABLE `table_name` (`id` INT UNSIGNED PRIMARY KEY, `namec` CHAR(255) NOT NULL DEFAULT "", `lurl` VARCHAR(500) NOT NULL DEFAULT "#", `ctg` CHAR(255) NOT NULL DEFAULT ":") CHARACTER SET utf8 COLLATE utf8_general_ci;\nINSERT INTO `table_name` (`id`, `namec`, `lurl`, `ctg`) VALUES ';

    // sets to adds the items data from ctgData as rows in SQL
    for(var i in ctgData) {
      addcode += "("+ i +", '"+ ctgData[i].namec +"', '"+ ctgData[i].lurl +"', '"+ ctgData[i].ctg +"'),";
    }

    return addcode.replace(/,$/, '');      // returns the code, deleting the last ','
  }

  // to add codes in textareas
  this.addTxtarea = function() {
    document.getElementById('htmlcode').value = '<div id="m_menu">'+ setHtml() +'</div>';
    document.getElementById('jsoncode').value = setJsonStr();
    document.getElementById('sqlcode').value = setSql();
     Ajax(0, 'return', document.getElementById('m_style').href);
  }

/** Get, Save, Ajax and Others **/

  // gets categories data saved in TXT file
  this.getData = function() {
    var resname = document.getElementById('getctg').value;        // resource /menu name

    // if $geto is 'txt', get data directly via Ajax, else, if 'mysql', gets with Ajax via php
    if(geto == 'txt') Ajax(0, 'get', 'menus/'+ resname +'.txt');
    else if(geto == 'mysql') Ajax('ctgres='+ resname +'&saveto='+ geto, 'get', 'setmenu/setmenu.php');

    thisob.tabShowHide('sets', 'gets', 'codes');    // switch to Set Data Tab
    document.getElementById('ctgres').value = resname;       // add resource name in text-field for saving data
  }

  // gets and pass data to Ajax, to be saved on server
  this.saveData = function() {
    // if it is added name for resource to save
    var ctgres = document.getElementById('ctgres');
    if(ctgres.value.match(/^[a-z0-9_-]{2,250}$/i)) {
      // sets data (pass categories structure in JSON)
      var datasend = 'ctgres='+ ctgres.value +'&sdata='+ encodeURIComponent(setJsonStr()) +'&saveto='+ saveto +'&admname='+ document.getElementById('admname').value +'&admpass='+ document.getElementById('admpass').value;
      Ajax(datasend, 'save', 'setmenu/setmenu.php');
    }
    else {
      ctgres.focus();
      alert(lang['errm_name']);
    }
  }

  // create the XMLHttpRequest object, according to browser
  function getXmlHttp() {
    var xmlHttp = null;           // will stere and return the XMLHttpRequest

    if(window.XMLHttpRequest) xmlHttp = new XMLHttpRequest();     // Forefox, Opera, Safari, ...
    else if(window.ActiveXObject) xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");     // IE

    return xmlHttp;
  }

  // sends data to PHP and receives the response
  function Ajax(datasend, req, tofile) {
    var ajaxreq =  getXmlHttp();		// get XMLHttpRequest object

    ajaxreq.open("POST", tofile, true);			// create the request

    ajaxreq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");    // header for POST
    ajaxreq.send(datasend +'&ajx=1');		//  make the ajax request, poassing the data

    // checks and receives the response
    ajaxreq.onreadystatechange = function() {
      if (ajaxreq.readyState == 4) {
        // if $req is 'css', adds response in textarea for css code
        // if is 'get', request to get data (JSON with two arrays, for $ctgItems, and $ctgData)
        // else, request to save data, and alerts response
        if(req == 'return') document.getElementById('csscode').value = ajaxreq.responseText;
        else if(req == 'get') {
          // if menu resource not exists, alerts message, else, gets the JSON, array with two objects, for $ctgItems and $ctgData
          if(ajaxreq.responseText.indexOf('not found!<') > 0) alert('The resource: "'+ document.getElementById('getctg').value +'" not found');
          else {
            var jsonob = JSON.parse(ajaxreq.responseText);
            ctgItems = jsonob[0];
            ctgData = jsonob[1];

            addSelCtgs();    // resets data and adds 1st <select> with main categories
          }
        }
        else if(req == 'save') alert(ajaxreq.responseText);
      }
    }
  }

  // for tab effec, receives the ID of element to show and IDs of elements to hide
  this.tabShowHide = function(sid, hid1, hid2) {
    document.getElementById(sid).style.display = 'block';
    document.getElementById(hid1).style.display = 'none';
    document.getElementById(hid2).style.display = 'none';

    // add class="tabvi" to tab that shows, and deletes it from the other tabs
    document.getElementById('tab'+sid).setAttribute('class', 'tabvi');
    document.getElementById('tab'+hid1).removeAttribute('class');
    document.getElementById('tab'+hid2).removeAttribute('class');
  }

  // to register events
  this.regEvets = function() {
    // for radio buttons, to change displayed menu style
    document.getElementById('hv_menu').onclick = function(){ document.getElementById('m_style').href = 'setmenu/'+ this.value+'.css'; thisob.tabShowHide('sets', 'gets', 'codes');};
    document.getElementById('vh_menu1').onclick = function(){ document.getElementById('m_style').href = 'setmenu/'+ this.value+'.css'; thisob.tabShowHide('sets', 'gets', 'codes');};
    document.getElementById('vh_menu2').onclick = function(){ document.getElementById('m_style').href = 'setmenu/'+ this.value+'.css'; thisob.tabShowHide('sets', 'gets', 'codes');};

    // for tab efect
    document.getElementById('tabgets').onclick = function(){ thisob.tabShowHide('gets', 'sets', 'codes');};
    document.getElementById('tabsets').onclick = function(){ thisob.tabShowHide('sets', 'gets', 'codes');};
    document.getElementById('tabcodes').onclick = function(){
      thisob.tabShowHide('codes', 'gets', 'sets');
      thisob.addTxtarea();
    };
    // tabs-codes
    document.getElementById('tabchtml').onclick = function(){ thisob.tabShowHide('chtml', 'cjson', 'csql');};
    document.getElementById('tabcjson').onclick = function(){ thisob.tabShowHide('cjson', 'chtml', 'csql');};
    document.getElementById('tabcsql').onclick = function(){ thisob.tabShowHide('csql', 'chtml', 'cjson');};

    // on change 1st select list
    document.getElementById('sl').onchange = function(){ this.addSubSelect(this); }

    // button to add/modify/delete category/sub-category
    document.getElementById('addctg').onclick = addCategory;
    document.getElementById('chgctg').onclick = modifyCategory;
    document.getElementById('delctg').onclick = deleteCategory;

    // for radio buttons that set from which resource type to get data
    document.getElementById('getxt').onclick = function(){ geto = this.value;};
    document.getElementById('getmysql').onclick = function(){ geto = this.value;};

    document.getElementById('btnget').onclick = thisob.getData;     // button to get data

    // for radio buttons that set where to save data
    document.getElementById('totxt').onclick = function(){ saveto = this.value;};
    document.getElementById('tomysql').onclick = function(){ saveto = this.value;};
    document.getElementById('toboth').onclick = function(){ saveto = this.value;};

    document.getElementById('btnsave').onclick = thisob.saveData;     // button to save data

    // to auto select data in textarea
    document.getElementById('htmlcode').onfocus = function(){ this.select();};
    document.getElementById('csscode').onfocus = function(){ this.select();};
    document.getElementById('jsoncode').onfocus = function(){ this.select();};
    document.getElementById('phpctxt').onfocus = function(){ this.select();};
    document.getElementById('sqlcode').onfocus = function(){ this.select();};
    document.getElementById('phpcmysql').onfocus = function(){ this.select();};
  }

  this.regEvets();
}

// create object to MakeSLists
var obMSL = new MakeSLists();