// DOM
function createIFrame(fname, src){
    var ifrstr = Browser.IE ? '<iframe name="'+fname+'" src="'+src+'">' : 'iframe';
    var cframe = document.createElement(ifrstr);
 
    with(cframe){ 
        name = fname // это не для IE
        setAttribute("name", fname) // и это тоже, но вреда не будет
        id = fname // а это везде ок
    }
 
    if(!Browser.IE){
        setIFrameSrc(cframe, src);
    }
 
    return cframe
}


function getElement(id) {
  if (typeof(id)=='object') {var element=id;}
  else {var element=((document.getElementById)?document.getElementById(id):document.all[id]);}

  return element;
}

function getIFrameDocument(id){ 
  var res = null; 
  var iframe=getElement(id);
  // if contentDocument exists, W3C 

  if(iframe.contentDocument) res = iframe.contentDocument;
  else if(iframe.contentWindow) res = iframe.contentWindow.document;
  else res = document.frames[id].document;

  return res;
}

function setIFrameSrc(id, src) {
  getIFrameDocument(id).location.replace(src);
  //var doc=getIFrameDocument(id);
  //alert('['+doc.location.href);
  //doc.location.assign(src);
  //doc.location.href=src;
  //alert(']'+doc.location.href);
}

function screenView() {
  var res;
  if (Browser.WebKit) {
    res={
      top: parseInt(document.body.scrollTop), 
      left: parseInt(document.body.scrollLeft), 
      width: parseInt(document.body.scrollWidth), 
      height: parseInt(document.body.scrollHeight)}
  } else {
    res={
      top: parseInt(document.documentElement.scrollTop), 
      left: parseInt(document.documentElement.scrollLeft), 
      width: parseInt(document.documentElement.scrollWidth), 
      height: parseInt(document.documentElement.scrollHeight)}
  }
  return(res);
}

function absolutePosition(id) {
  var offsetLeft = 0, offsetTop = 0;
  
  if (typeof(id)=='object') {var element=id;}
  else {var element=$(id);}
	var pos=element.getPosition();
  return ({x:pos.x, y:pos.y, left:pos.x, top:pos.y});
/*
  if (typeof(id)=='object') {var element=id;}
  else {var element=document.getElementById(id);}

  do {
      offsetLeft += element.offsetLeft;
      offsetTop  += element.offsetTop;
  } while (element = element.offsetParent);
  if (Browser) {
    if (!(Browser.Gecko || Browser.WebKit)) {
      //offsetLeft-=10; offsetTop-=10;
    }
    if (Browser.Opera) {offsetLeft-=10;offsetTop-=10;}
    else if (Browser.IE) {offsetLeft-=10;offsetTop-=10;}
  }
  return ({x:offsetLeft, y:offsetTop, left:offsetLeft, top:offsetTop});
*/
}

function setPosition(id, x, y) {
	$(id).setPosition({x:x, y:y});
	return;
	
//alert(id);
/*
  var el=document.getElementById(id);
  el.style.left=x+'px';
  el.style.top=y+'px';
*/
}

function setElementsPos(parent, arr) {
  var p=absolutePosition(parent);
  var div;
  for(i=0;i<arr.length;i++) {
    setPosition(arr[i].id, arr[i].x+p.x, arr[i].y+p.y);
    if (arr[i].id.substring(0, 3)=='st_') {
      setPosition('stn'+arr[i].id.substring(3), arr[i].x1+p.x, arr[i].y1+p.y);
    }
  }
}

/*
   1.Первый параметр используется для выбора элементов по имени тега. Необязательный.
          * child() — пустое значение, функция вернет массив всех дочерних узлов.
          * child('div') — cтрока с именем тега, функция вернет массив дочерних узлов с именем тега "DIV".
          * child('div h1 p') — строка со списком имен тегов, разделенных пробелами, функция вернет массив дочерних элементов с именами тегов "DIV", "H1" и "P".
          * child(['div', 'h1', 'p']) — массив строк с именами тегов, результат выполнения функции аналогичен предыдущему пункту.
   2.Второй параметр логического типа так же необязателен и используется для переключения режима поиска дочерних элементов. Может принимать пустое значение или true. Если указано значение true, то будут выбраны все дочерние элементы, текущего узла, соответствующие критериям поиска, указанным в первом параметре, иначе — только непосредственно дочерние по отношению к текущему узлу. Допускается сочетание этого параметра со всеми вариантами первого параметра:
          * child(true)
          * child('div', true)
          * child('div h1 p', true)
          * child(['div', 'h1', 'p'], true)
*/
function getChild(id, tag) {
  var node = document.getElementById(id),
  children = node.childNodes,
  i, length = children.length, array = [];
  tag = tag.toUpperCase();
  for(i = 0; i < length; i++) {
    if(children[i].tagName == tag) {
      array.push(children[i]);
    }
  }
  return array;
}

function setOpacity(obj, val) {
  var old;
  
  if (val>1) val=val/100;
  obj=getElement(obj);
  if (obj.opacity) old=obj.opacity;
  obj.style.filter='alpha(opacity='+Math.round(val*100)+')';
  obj.style.opacity=val;
  obj.style['-moz-opacity']=val;
  obj.style['-khtml-opacity']=val;
  
  return(old);
}

function serialize( mixed_value ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Arpad Ray (mailto:arpad@php.net)
    // +   improved by: Dino
    // +   bugfixed by: Andrej Pavlovic
    // +   bugfixed by: Garagoth
    // %          note: We feel the main purpose of this function should be to ease the transport of data between php & js
    // %          note: Aiming for PHP-compatibility, we have to translate objects to arrays
    // *     example 1: serialize(['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}'
    // *     example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'});
    // *     returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}'
 
    var _getType = function( inp ) {
        var type = typeof inp, match;
        var key;
        if (type == 'object' && !inp) {
            return 'null';
        }
        if (type == "object") {
            if (!inp.constructor) {
                return 'object';
            }
            var cons = inp.constructor.toString();
            if (match = cons.match(/(\w+)\(/)) {
                cons = match[1].toLowerCase();
            }
            var types = ["boolean", "number", "string", "array"];
            for (key in types) {
                if (cons == types[key]) {
                    type = types[key];
                    break;
                }
            }
        }
        return type;
    };
    var type = _getType(mixed_value);
    var val, ktype = '';
    
    switch (type) {
        case "function": 
            val = ""; 
            break;
        case "undefined":
            val = "N";
            break;
        case "boolean":
            val = "b:" + (mixed_value ? "1" : "0");
            break;
        case "number":
            val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value;
            break;
        case "string":
            val = "s:" + mixed_value.length + ":\"" + mixed_value + "\"";
            break;
        case "array":
        case "object":
            val = "a";
            /*
            if (type == "object") {
                var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/);
                if (objname == undefined) {
                    return;
                }
                objname[1] = serialize(objname[1]);
                val = "O" + objname[1].substring(1, objname[1].length - 1);
            }
            */
            var count = 0;
            var vals = "";
            var okey;
            var key;
            for (key in mixed_value) {
                ktype = _getType(mixed_value[key]);
                if (ktype == "function") { 
                    continue; 
                }
                
                okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key);
                vals += serialize(okey) +
                        serialize(mixed_value[key]);
                count++;
            }
            val += ":" + count + ":{" + vals + "}";
            break;
    }
    if (type != "object" && type != "array") {
      val += ";";
  }
    return val;
}

// =========================


function stationSelect(id) {
  var img=document.getElementById(id);
  var val=id.substring(3);
  var div=document.getElementById('stn'+val);
  if (oMetroSelect.options.length>nMetroSelectMax) {
    msgAlert('Количество выбранных станций метро не может быть больше '+nMetroSelectMax+'\n '+
    'Если Вы хотите, чтобы в результаты были включены все станции метро, оставьте список пустым.');
    return (false);
  }
  img.src='/img/metro-sel.gif';
  if (div && div.title>'') {
    oMetroSelect.options[oMetroSelect.options.length] = new Option(div.title, val, true, true);
  }
  var el=document.getElementById('sel_metro_num');
  if (el) el.textContent='Выбрано: '+oMetroSelect.options.length;
  return (true);
}


function stationUnSelect(id) {
  var img=document.getElementById(id);
  var val=id.substring(3);
  img.src='/img/metro-nul.gif';
  for (var i=0;i<oMetroSelect.options.length;i++){
    if (oMetroSelect.options[i].value==val) {
      oMetroSelect.options[i]=null; 
      break;
    }
  }

  for (var i=0;i<oMetroSelect.options.length;i++){
    oMetroSelect.options[i].selected=true; 
  }

  document.getElementById('sel_metro_num').textContent='Выбрано: '+oMetroSelect.options.length;
  return (true);
}


function getStationFromSelect(val) {
  var res=-1;
  for (i=0;i<oMetroSelect.options.length;i++){
    if (oMetroSelect.options[i].value==val) {res=i;break;}
  }
  return(res);
}

function stationFillList() {
  var val = '';
  var el=document.getElementById('sel_metro');
  for (i=0;i<el.options.length;i++) {val+=el.options[i].value+' ';}
  document.getElementById('sel_metro_list').value=val;
}


function clickStation(id) {
  var res=true;
  var img, val=id.substring(3);
  if (img=document.getElementById(id)) {
    for (i=0;i<oMetroSelect.options.length;i++){
      if (oMetroSelect.options[i].value==val) {break;}
    }
    if (src=img.src.substring(img.src.length-7)=='sel.gif') {
      res=stationUnSelect(id);
    } else {
      res=stationSelect(id);
    }
  }
  metroSeek('');
  return (res);
}

function clickMetro(o) {
  var id='st_'+o.options[o.selectedIndex].value;
  clickStation(id);
}

function clickLine(id) {
  var res=true;
  var ln=id.substring(3);
  var i, val, idx;
  for (i=0;i<stations.length;i++) {
    if (stations[i].ln==ln) {
      val=stations[i].id.substring(3);
      idx=getStationFromSelect(val);
      if (idx==-1) res=clickStation('st_'+val);
      if (!res) break;
    }
  }
}


function metroClearAll() {
  var arr=new Array();
  for (i=0;i<oMetroSelect.options.length;i++){
    arr[i]='st_'+oMetroSelect.options[i].value;
  }
  for (i=0;i<arr.length;i++){stationUnSelect(arr[i]);}
}

function metroSetSelectList(list) {
  if (!list) return;
  for(var i=0; i<list.length; i++) {
    clickStation('st_'+list[i]);
  }
}


function drawMetro(list) {
  if (!oMetroSelect) oMetroSelect=document.getElementById('sel_metro');
  drawStations();
  drawLines();
  if (list) metroSetSelectList(list); 
}

function metroSeek(s) {
  if (!s) s='';
  var div, sel;
  var len=s.length;
  if (len) {
    s=s.toLowerCase();
    for (var i=0; i<stations.length; i++) {
      if (stations[i].name.toLowerCase().substring(0, len)==s) {
      //a.push(s);
        sel=document.getElementById('stn000');
        div=document.getElementById('stn'+stations[i].id.substring(3));
        sel.style.width=div.style.width;
        sel.style.height=div.style.height;
        var coord=absolutePosition(div);
        setPosition('stn000', coord.x-1, coord.y-1);
        document.getElementById('metro_seek_text').innerHTML='<span style="font-weight:bold;">'+stations[i].name.substring(0,len)+'</span><span style="color:#777;">'+stations[i].name.substring(len,255)+'</span>';
        document.getElementById('metro_seek_but').disabled=false;
        document.getElementById('metro_seek_id').value=stations[i].id;
      }
    }
  } else {
    document.getElementById('metro_seek_text').innerHTML='';
    document.getElementById('metro_seek_but').disabled=true;
    setPosition('stn000', -1000, -1000);
    document.getElementById('metro_seek').value='';
    document.getElementById('metro_seek_id').value='';
  }
}

function metroSeekSelect() {
  var res=clickStation(document.getElementById('metro_seek_id').value);
//  metroSeek('');
  return (res);
}

function msgAlert(msg) {
  alert(msg);
  err++;
}

function msgConfirm(msg) {
  var res=confirm(msg)
  if (!res) err++;
  return(res);
}

function clearMessageBeg(msg, tag) {
  var len=tag.length;
  while (msg.toLowerCase().indexOf(tag)==0) {msg=msg.substring(len);}
  return(msg);
}


function clearMessage(msg) {
  msg = msg.replace(new RegExp("/\s{2,}/"), "\n");
  msg = msg.replace(new RegExp("/\n{2,}/"), "\n");
  
  msg = clearMessageBeg(msg, '<br>');
  msg = clearMessageBeg(msg, '<br />');
  return(msg);
}


function changeImg(id, src) {
  var img=getElement(id);
  if (img) img.src='/img/'+src;
  //alert(img.src);
}


var oMetroSelect=false;
var nMetroSelectMax=100;

Browser.IE = Browser.Engine.trident;
Browser.Opera = Browser.Engine.presto;
Browser.WebKit = Browser.Engine.webkit;
Browser.Gecko = Browser.Engine.gecko;
Browser.MobileSafari = !!navigator.userAgent.match(/Apple.*Mobile.*Safari/);


