<?xml version='1.0'?>
<!DOCTYPE bindings [
<!ENTITY % altsearchDTD SYSTEM "/altsearch.dtd">
%altsearchDTD;
]>
<bindings xmlns:xbl="http://www.mozilla.org/xbl" xmlns="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

    <binding id="panel">
        <resources>
            <stylesheet src="panel.css"/>
        </resources>

        <content hidden="true">
            <hbox anonid="container" flex="1" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
                <hbox anonid="search-box" flex="1">
                    <label value="&wgt.altsearch.searchAnother.start.label; «"/>
                    <label anonid="search-string-full" class="bold" xbl:inherits="value=searchString"/>
                    <label anonid="search-string-cropped" class="bold" crop="end" flex="1" hidden="true" xbl:inherits="value=searchString"/>
                    <label value="» &wgt.altsearch.searchAnother.end.label;:"/>
                    <hbox anonid="search-engines"/>
                </hbox>
                <hbox anonid="image-box">
                    <image onclick="if (event.button !== 2) _openComponentSettings();"/>
                    <image onclick="if (event.button !== 2) _hideForCurrentPage();"/>
                </hbox>
            </hbox>
        </content>

        <implementation implements="nsIDOMEventListener">
            <field name="mSearchBox">document.getAnonymousElementByAttribute(this, "anonid", "search-box")</field>
            <field name="mFullSearchString">document.getAnonymousElementByAttribute(this, "anonid", "search-string-full")</field>
            <field name="mCroppedSearchString">document.getAnonymousElementByAttribute(this, "anonid", "search-string-cropped")</field>
            <field name="mSearchEngines">document.getAnonymousElementByAttribute(this, "anonid", "search-engines")</field>
            <field name="mWinListener">this.module.API.Browser.getWindowListener(window)</field>

            <field name="_windowEventsListen">false</field>
            <field name="_previousWindowWidth">0</field>

            <property name="currentBrowser" onget="return gBrowser.mCurrentBrowser;" readonly="true"/>

            <property name="contentWindow" onget="return this.currentBrowser.contentWindow;" readonly="true"/>

            <property name="contentDocument" onget="return this.currentBrowser.contentDocument;" readonly="true"/>

            <constructor><![CDATA[const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
this.module.searchEnginesInfo.forEach(function (engine) {
var label = document.createElementNS(XUL_NS,"label");
label.setAttribute("value",engine.name);
label.setAttribute("data-engine-id",engine.id);
this.mSearchEngines.appendChild(label);
}
,this);
this.mSearchBox.addEventListener("overflow",this,false);
this.mSearchEngines.addEventListener("click",this,false);
this.setAttribute("data-ya-os",this.module.API.Environment.os.name);]]></constructor>

            <destructor><![CDATA[this.mSearchBox.removeEventListener("overflow",this,false);
this.mSearchEngines.removeEventListener("click",this,false);
this.mWinListener.removeAllTabData("altSearchTabData");]]></destructor>

            <method name="fill">
                <parameter name="aEngineId"/>
                <parameter name="aSearchString"/>
                <body><![CDATA[this.setAttribute("searchString",aSearchString);
this.mCroppedSearchString.hidden = true;
this.mFullSearchString.hidden = false;
Array.slice(this.mSearchEngines.querySelectorAll("label[data-engine-id]")).forEach(function (label) label.hidden = label.getAttribute("data-engine-id") === aEngineId);
if (! this._windowEventsListen)
{
this._windowEventsListen = true;
window.addEventListener("scroll",this,false);
window.addEventListener("resize",this,false);
}

var readyState = this.contentDocument.readyState;
setTimeout((function () {
this._checkPageScroll(true);
}
).bind(this),readyState == "complete" ? 0 : 2000);
this._previousWindowWidth = window.innerWidth;]]></body>
            </method>

            <method name="hide">
                <body><![CDATA[if (this._windowEventsListen)
{
this._windowEventsListen = false;
window.removeEventListener("scroll",this,false);
window.removeEventListener("resize",this,false);
}

this.hidden = true;]]></body>
            </method>

            <method name="_hideForCurrentPage">
                <body><![CDATA[var tabData = this.mWinListener.getTabData(this.currentBrowser,"altSearchTabData");
if (tabData)
tabData.closedByUser = true;
this.hide();]]></body>
            </method>

            <method name="_checkPageScroll">
                <parameter name="aWaitOnNullScroll"/>
                <body><![CDATA[if (! this.hidden)
return;
var [, searchString] = this.module.getSearchPropsFromURI(this.currentBrowser.currentURI);
if (! searchString)
{
this.hide();
return;
}

var tabData = this.mWinListener.getTabData(this.currentBrowser,"altSearchTabData");
if ("url" in tabData)
{
if (tabData.url === this.contentWindow.location.href)
{
if (tabData.closedByUser)
{
this.hide();
}
else
{
this.setSearchBoxMargin();
this.hidden = false;
}

return;
}
else
{
delete tabData.url;
delete tabData.closedByUser;
}

}

var {scrollY: scrollY, scrollMaxY: scrollMaxY} = this.contentWindow;
if (aWaitOnNullScroll && scrollY == 0 && scrollMaxY == 0)
{
setTimeout(this._checkPageScroll.bind(this),2000);
return;
}

if (scrollMaxY * 0.05 < scrollMaxY - scrollY)
return;
tabData.url = this.contentWindow.location.href;
this.setSearchBoxMargin();
this.hidden = false;
this.module.API.Statistics.logCustomAction(100);
var request = new XMLHttpRequest();
request.open("GET","http://clck.yandex.ru/click/dtype=stred/pid=12/cid=72213/*",true);
request.send(null);]]></body>
            </method>

            <method name="setSearchBoxMargin">
                <body><![CDATA[var leftMargin = 20;
var inputName = this.module.getPageInputName(gBrowser.currentURI);
if (inputName)
{
let input = this.contentDocument.querySelector("input[name='" + inputName + "']");
if (input)
{
try {
let formMargin = Math.max(leftMargin,input.getBoundingClientRect().left);
if (formMargin < this.contentWindow.innerWidth / 2)
leftMargin = formMargin;
}
catch (e) {

}

}

}

this.mSearchBox.style.marginLeft = leftMargin + "px";]]></body>
            </method>

            <method name="_sendStatistic">
                <parameter name="engineId"/>
                <body><![CDATA[var url = "http://clck.yandex.ru/click/dtype=stred/pid=12/cid=72213/" + "path=" + encodeURIComponent(engineId) + "/*";
var request = new XMLHttpRequest();
request.open("GET",url,true);
request.send(null);]]></body>
            </method>

            <method name="handleEvent">
                <parameter name="aEvent"/>
                <body><![CDATA[switch (aEvent.type) {
case "click":
{
if (aEvent.target.localName !== "label")
return;
if (aEvent.button === 2)
return;
let engineId = aEvent.target.getAttribute("data-engine-id");
if (! engineId)
return;
let searchString = this.getAttribute("searchString");
let {prepearedQuery: prepearedQuery, action: action} = this.module.getEngineData(engineId,searchString);
this.module.API.Controls.navigateBrowser({
url: prepearedQuery,
target: "new tab",
eventInfo: aEvent});
if (action)
this.module.API.Statistics.logCustomAction(action);
this._sendStatistic(engineId);
break;
}

case "scroll":
this._checkPageScroll();
break;
case "resize":
if (aEvent.target !== aEvent.currentTarget)
return;
let previousWidth = this._previousWindowWidth;
this._previousWindowWidth = window.innerWidth;
if (window.innerWidth - previousWidth < 0)
return;
if (this.mCroppedSearchString.hidden)
return;
if (! this.mCroppedSearchString.boxObject.width)
return;
setTimeout((function (text) {
this.mCroppedSearchString.hidden = true;
this.mFullSearchString.hidden = false;
}
).bind(this),0);
break;
case "overflow":
if (aEvent.target !== aEvent.currentTarget)
return;
if (aEvent.detail == 0)
return;
this.mCroppedSearchString.hidden = false;
this.mFullSearchString.hidden = true;
break;
}
]]></body>
            </method>

            <method name="_openComponentSettings">
                <body><![CDATA[this.module.API.Controls.openSettingsDialog(null,this.module.API.componentID);]]></body>
            </method>
        </implementation>
    </binding>

    <binding id="button">
        <implementation implements="nsIObserver">
            <field name="API" readonly="true">this.module.API</field>
            <field name="mPanel">null</field>
            <field name="mWinListener">this.API.Browser.getWindowListener(window)</field>

            <constructor><![CDATA[this.wdgtxConstructor();]]></constructor>

            <destructor><![CDATA[this.wdgtxDestructor();]]></destructor>

            <method name="wdgtxConstructor">
                <body><![CDATA[if (this._wdgtxConstructed)
return;
this._wdgtxConstructed = true;
this._createPanel();
window.setTimeout((function wdgtxConstructorTimed() {
if (! this._wdgtxConstructed)
return;
this.mWinListener.addListener("WindowLocationChange",this);
this.mWinListener.addListener("DOMContentLoaded",this);
if (! (this.mPanel && this.mPanel.hidden))
return;
try {
if (gBrowser.mCurrentBrowser.contentDocument.readyState === "loading")
return;
}
catch (e) {

}

this._processURI(gBrowser.currentURI);
}
).bind(this),500);]]></body>
            </method>

            <method name="wdgtxDestructor">
                <body><![CDATA[if (! this._wdgtxConstructed)
return;
this._wdgtxConstructed = false;
this.mWinListener.removeListener("WindowLocationChange",this);
this.mWinListener.removeListener("DOMContentLoaded",this);
this._removePanel();]]></body>
            </method>

            <method name="observe">
                <parameter name="subject"/>
                <parameter name="topic"/>
                <parameter name="data"/>
                <body><![CDATA[if (! data.isCurrentTab)
return;
switch (topic) {
case "WindowLocationChange":
this._hidePanel();
if (data.readyState === "loading")
return;
case "DOMContentLoaded":
let doc = data.tab.contentDocument;
if (! /^https?:\/\//.test(doc.documentURI) || ! /[^x]html/.test(doc.contentType))
{
this._hidePanel();
return;
}

if (topic === "DOMContentLoaded")
{
let tabData = this.mWinListener.getTabData(gBrowser.mCurrentBrowser,"altSearchTabData");
if (tabData)
delete tabData.closedByUser;
}

this._processURI(data.uri);
break;
}
]]></body>
            </method>

            <method name="_processURI">
                <parameter name="aURI"/>
                <body><![CDATA[var [searchId, searchString] = this.module.getSearchPropsFromURI(aURI);
if (! searchString)
{
this._hidePanel();
return;
}

this._showPanel(searchId,searchString);]]></body>
            </method>

            <method name="_showPanel">
                <parameter name="aEngineId"/>
                <parameter name="aSearchString"/>
                <body><![CDATA[if (! this.mPanel)
this._createPanel();
if (this.mPanel && typeof this.mPanel.fill == "function")
this.mPanel.fill(aEngineId,aSearchString);]]></body>
            </method>

            <method name="_hidePanel">
                <body><![CDATA[if (this.mPanel && typeof this.mPanel.hide == "function")
this.mPanel.hide();]]></body>
            </method>

            <method name="_createPanel">
                <body><![CDATA[const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var panel = document.createElementNS(XUL_NS,"hbox");
panel.setAttribute("id",this.module.PANEL_ID);
var browserBottombox = document.getElementById("browser-bottombox");
browserBottombox.parentNode.insertBefore(panel,browserBottombox);
panel.module = this.module;
this.mPanel = panel;]]></body>
            </method>

            <method name="_removePanel">
                <body><![CDATA[if (! this.mPanel)
return;
if (this.mPanel.parentNode)
this.mPanel.parentNode.removeChild(this.mPanel);
delete this.mPanel.module;
this.mPanel = null;]]></body>
            </method>
        </implementation>
    </binding>
</bindings>
