From ed811d0431405bf960d6a1bb91813f731e72ff27 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 28 Jul 2016 15:01:21 -0700 Subject: [PATCH 001/134] replace Row with ListView, but otherwise same user-functionality --- interface/resources/qml/AddressBarDialog.qml | 58 ++++++++++---------- interface/resources/qml/hifi/Card.qml | 11 ++-- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 792410c59d..df34295a0f 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -46,7 +46,7 @@ Window { } function goCard(card) { - addressLine.text = card.userStory.name; + addressLine.text = card.path; toggleOrGo(true); } property var allDomains: []; @@ -60,32 +60,27 @@ Window { implicitWidth: backgroundImage.width implicitHeight: backgroundImage.height - Row { - width: backgroundImage.width; + ListModel { id: suggestions } + + ListView { + width: (3 * cardWidth) + (2 * hifi.layout.spacing); + height: cardHeight; + spacing: hifi.layout.spacing; anchors { bottom: backgroundImage.top; bottomMargin: 2 * hifi.layout.spacing; right: backgroundImage.right; - rightMargin: -104; // FIXME } - spacing: hifi.layout.spacing; - Card { - id: s0; + model: suggestions; + orientation: ListView.Horizontal; + delegate: Card { width: cardWidth; height: cardHeight; - goFunction: goCard - } - Card { - id: s1; - width: cardWidth; - height: cardHeight; - goFunction: goCard - } - Card { - id: s2; - width: cardWidth; - height: cardHeight; - goFunction: goCard + goFunction: goCard; + path: model.name; + thumbnail: model.thumbnail; + placeText: model.name; + usersText: model.online_users + ((model.online_users === 1) ? ' user' : ' users') } } @@ -225,6 +220,7 @@ Window { function addPictureToDomain(domainInfo, cb) { // asynchronously add thumbnail and lobby to domainInfo, if available, and cb(error) // This requests data for all the names at once, and just uses the first one to come back. // We might change this to check one at a time, which would be less requests and more latency. + domainInfo.thumbnail = ''; // Regardless of whether we fill it in later, qt models must start with the all values they will have. asyncEach([domainInfo.name].concat(domainInfo.names || null).filter(identity), function (name, icb) { var url = "https://metaverse.highfidelity.com/api/v1/places/" + name; getRequest(url, function (error, json) { @@ -280,17 +276,19 @@ Window { } function filterChoicesByText() { - function fill1(target, data) { + function fill1(targetIndex, data) { if (!data) { - target.visible = false; + if (targetIndex < suggestions.count) { + suggestions.remove(targetIndex); + } return; } console.log('suggestion:', JSON.stringify(data)); - target.userStory = data; - target.image.source = data.lobby || target.defaultPicture; - target.placeText = data.name; - target.usersText = data.online_users + ((data.online_users === 1) ? ' user' : ' users'); - target.visible = true; + if (suggestions.count <= targetIndex) { + suggestions.append(data); + } else { + suggestions.set(targetIndex, data); + } } var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity); var filtered = !words.length ? suggestionChoices : allDomains.filter(function (domain) { @@ -303,9 +301,9 @@ Window { return text.indexOf(word) >= 0; }); }); - fill1(s0, filtered[0]); - fill1(s1, filtered[1]); - fill1(s2, filtered[2]); + fill1(0, filtered[0]); + fill1(1, filtered[1]); + fill1(2, filtered[2]); } function fillDestinations() { diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index 7758c5800a..4996bc9789 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -18,27 +18,28 @@ import "../styles-uit" Rectangle { property var goFunction: null; - property var userStory: null; property alias image: lobby; property alias placeText: place.text; property alias usersText: users.text; property int textPadding: 20; property int textSize: 24; - property string defaultPicture: "../../images/default-domain.gif"; + property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif"); + property string thumbnail: defaultThumbnail; + property string path: ""; HifiConstants { id: hifi } Image { id: lobby; width: parent.width; height: parent.height; - source: defaultPicture; + source: thumbnail || defaultThumbnail; fillMode: Image.PreserveAspectCrop; // source gets filled in later anchors.verticalCenter: parent.verticalCenter; anchors.left: parent.left; onStatusChanged: { if (status == Image.Error) { - console.log("source: " + source + ": failed to load " + JSON.stringify(userStory)); - source = defaultPicture; + console.log("source: " + source + ": failed to load " + path); + source = defaultThumbnail; } } } From ff17761769cd688a7fc01a935e620f39d4d2be2e Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 28 Jul 2016 15:46:32 -0700 Subject: [PATCH 002/134] basic minority-report scroll (fixed initial data, but infinite cards) --- interface/resources/qml/AddressBarDialog.qml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index df34295a0f..6d60ba7749 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -66,6 +66,7 @@ Window { width: (3 * cardWidth) + (2 * hifi.layout.spacing); height: cardHeight; spacing: hifi.layout.spacing; + clip: true; anchors { bottom: backgroundImage.top; bottomMargin: 2 * hifi.layout.spacing; @@ -245,7 +246,7 @@ Window { if (!domainsBaseUrl) { var domainsOptions = [ 'open', // published hours handle now - 'active', // has at least one person connected. FIXME: really want any place that is verified accessible. + // fixme hrs restore 'active', // has at least one person connected. FIXME: really want any place that is verified accessible. // FIXME: really want places I'm allowed in, not just open ones. 'restriction=open', // Not by whitelist, etc. FIXME: If logged in, add hifi to the restriction options, in order to include places that require login. // FIXME add maturity @@ -276,7 +277,8 @@ Window { } function filterChoicesByText() { - function fill1(targetIndex, data) { + function fill1(targetIndex) { + var data = filtered[targetIndex]; if (!data) { if (targetIndex < suggestions.count) { suggestions.remove(targetIndex); @@ -301,9 +303,7 @@ Window { return text.indexOf(word) >= 0; }); }); - fill1(0, filtered[0]); - fill1(1, filtered[1]); - fill1(2, filtered[2]); + for (var index in filtered) { fill1(index); } } function fillDestinations() { @@ -316,13 +316,13 @@ Window { var here = AddressManager.hostname; // don't show where we are now. allDomains = domains.filter(function (domain) { return domain.name !== here; }); // Whittle down suggestions to those that have at least one user, and try to get pictures. - suggestionChoices = allDomains.filter(function (domain) { return domain.online_users; }); + suggestionChoices = allDomains.filter(function (domain) { return true/*fixme hrs restore domain.online_users*/; }); asyncEach(domains, addPictureToDomain, function (error) { if (error) { console.log('place picture query failed:', error); } // Whittle down more by requiring a picture. - suggestionChoices = suggestionChoices.filter(function (domain) { return domain.lobby; }); + // fixme hrs restore suggestionChoices = suggestionChoices.filter(function (domain) { return domain.lobby; }); filterChoicesByText(); }); }); From ae9421f1f69652ee590fbdfd7d92fd587515f8bf Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 29 Jul 2016 15:22:08 -0700 Subject: [PATCH 003/134] smaller user label, and use the word "people" --- interface/resources/qml/AddressBarDialog.qml | 2 +- interface/resources/qml/hifi/Card.qml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 6d60ba7749..ef8f297a75 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -81,7 +81,7 @@ Window { path: model.name; thumbnail: model.thumbnail; placeText: model.name; - usersText: model.online_users + ((model.online_users === 1) ? ' user' : ' users') + usersText: model.online_users + ((model.online_users === 1) ? ' person' : ' people'); } } diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index 4996bc9789..ba26c51bf8 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -23,6 +23,7 @@ Rectangle { property alias usersText: users.text; property int textPadding: 20; property int textSize: 24; + property int textSizeSmall: 18; property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif"); property string thumbnail: defaultThumbnail; property string path: ""; @@ -80,7 +81,7 @@ Rectangle { } RalewayRegular { id: users; - size: textSize; + size: textSizeSmall; color: hifi.colors.white; anchors { bottom: parent.bottom; From 611223f0134c14f8d75ed8047866db35130e98be Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 29 Jul 2016 15:49:20 -0700 Subject: [PATCH 004/134] highlight to show that the cards can be clicked --- interface/resources/qml/AddressBarDialog.qml | 3 +++ interface/resources/qml/hifi/Card.qml | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index ef8f297a75..6da55c59d4 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -82,7 +82,10 @@ Window { thumbnail: model.thumbnail; placeText: model.name; usersText: model.online_users + ((model.online_users === 1) ? ' person' : ' people'); + hoverThunk: function () { ListView.view.currentIndex = index; } + unhoverThunk: function () { ListView.view.currentIndex = -1; } } + highlight: Rectangle { color: "transparent"; border.width: 2; border.color: "#1FA5E8"; z: 1; } } Image { diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index ba26c51bf8..5fae628283 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -89,10 +89,15 @@ Rectangle { margins: textPadding; } } + property var hoverThunk: function () { }; + property var unhoverThunk: function () { }; MouseArea { + id: zmouseArea; anchors.fill: parent; acceptedButtons: Qt.LeftButton; onClicked: goFunction(parent); hoverEnabled: true; + onEntered: hoverThunk(); + onExited: unhoverThunk(); } } From 7cf41d441ecbfa76210cde844fa584c223c5d713 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 1 Aug 2016 12:28:57 -0700 Subject: [PATCH 005/134] filtering by place --- interface/resources/qml/AddressBarDialog.qml | 237 ++++++++++--------- 1 file changed, 128 insertions(+), 109 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 6da55c59d4..b80ab579c8 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -49,9 +49,7 @@ Window { addressLine.text = card.path; toggleOrGo(true); } - property var allDomains: []; - property var suggestionChoices: []; - property var domainsBaseUrl: null; + property var allPlaces: []; property int cardWidth: 200; property int cardHeight: 152; @@ -78,7 +76,7 @@ Window { width: cardWidth; height: cardHeight; goFunction: goCard; - path: model.name; + path: model.name + model.path; thumbnail: model.thumbnail; placeText: model.name; usersText: model.online_users + ((model.online_users === 1) ? ' person' : ' people'); @@ -199,135 +197,156 @@ Window { request.open("GET", url, true); request.send(); } - // call iterator(element, icb) once for each element of array, and then cb(error) when icb(error) has been called by each iterator. - // short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.) - function asyncEach(array, iterator, cb) { - var count = array.length; - function icb(error) { - if (!--count || error) { - count = -1; // don't cb multiple times (e.g., if error) - cb(error); - } - } + function asyncMap(array, iterator, cb) { + // call iterator(element, icb) once for each element of array, and then cb(error, mappedResult) + // when icb(error, mappedElement) has been called by each iterator. + // Calls to iterator are overlapped and map call icb in any order, but the mappedResults are collected in the same + // order as the elements of the array. + // short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.) + var count = array.length, results = []; if (!count) { - return cb(); + return cb(null, results); } - array.forEach(function (element) { - iterator(element, icb); + array.forEach(function (element, index) { + if (count < 0) { // don't keep iterating after we short-circuit + return; + } + iterator(element, function (error, mapped) { + results[index] = mapped; + if (error || !--count) { + count = 1; // don't cb multiple times if error + cb(error, results); + } + }); }); } + // Example: + /*asyncMap([0, 1, 2, 3, 4, 5, 6], function (elt, icb) { + console.log('called', elt); + setTimeout(function () { + console.log('answering', elt); + icb(null, elt); + }, Math.random() * 1000); + }, console.log); */ function identity(x) { return x; } - function addPictureToDomain(domainInfo, cb) { // asynchronously add thumbnail and lobby to domainInfo, if available, and cb(error) - // This requests data for all the names at once, and just uses the first one to come back. - // We might change this to check one at a time, which would be less requests and more latency. - domainInfo.thumbnail = ''; // Regardless of whether we fill it in later, qt models must start with the all values they will have. - asyncEach([domainInfo.name].concat(domainInfo.names || null).filter(identity), function (name, icb) { - var url = "https://metaverse.highfidelity.com/api/v1/places/" + name; - getRequest(url, function (error, json) { - var previews = !error && json.data.place.previews; - if (previews) { - if (!domainInfo.thumbnail) { // just grab the first one - domainInfo.thumbnail = previews.thumbnail; - } - if (!domainInfo.lobby) { - domainInfo.lobby = previews.lobby; - } - } - icb(error); - }); - }, cb); + function handleError(error, data, cb) { // cb(error) and answer truthy if needed, else falsey + if (!error && (data.status === 'success')) { + return; + } + cb(error || new Error(data.status + ': ' + data.error)); + return true; } - function getDomains(options, cb) { // cb(error, arrayOfData) - if (!options.page) { - options.page = 1; - } - if (!domainsBaseUrl) { - var domainsOptions = [ - 'open', // published hours handle now - // fixme hrs restore 'active', // has at least one person connected. FIXME: really want any place that is verified accessible. - // FIXME: really want places I'm allowed in, not just open ones. - 'restriction=open', // Not by whitelist, etc. FIXME: If logged in, add hifi to the restriction options, in order to include places that require login. - // FIXME add maturity - 'protocol=' + encodeURIComponent(AddressManager.protocolVersion()), - 'sort_by=users', - 'sort_order=desc', - ]; - domainsBaseUrl = "https://metaverse.highfidelity.com/api/v1/domains/all?" + domainsOptions.join('&'); - } - var url = domainsBaseUrl + "&page=" + options.page + "&users=" + options.minUsers + "-" + options.maxUsers; - getRequest(url, function (error, json) { - if (!error && (json.status !== 'success')) { - error = new Error("Bad response: " + JSON.stringify(json)); - } - if (error) { - error.message += ' for ' + url; - return cb(error); - } - var domains = json.data.domains; - if (json.current_page < json.total_pages) { - options.page++; - return getDomains(options, function (error, others) { - cb(error, domains.concat(others)); - }); - } - cb(null, domains); - }); - } - - function filterChoicesByText() { - function fill1(targetIndex) { - var data = filtered[targetIndex]; - if (!data) { - if (targetIndex < suggestions.count) { - suggestions.remove(targetIndex); - } + function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description + getRequest('https://metaverse.highfidelity.com/api/v1/places/' + placeData.name, function (error, data) { + if (handleError(error, data, cb)) { return; } - console.log('suggestion:', JSON.stringify(data)); - if (suggestions.count <= targetIndex) { - suggestions.append(data); - } else { - suggestions.set(targetIndex, data); + var place = data.data.place, previews = place.previews; + placeData.path = place.path; + if (previews && previews.thumbnail) { + placeData.thumbnail = previews.thumbnail; } + if (place.description) { + placeData.description = place.description; + placeData.searchText += ' ' + place.description.toUpperCase(); + } + cb(error, placeData); + }); + } + function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData) + function addPlace(name, icb) { + getPlace({ + name: name, + tags: domain.tags, + thumbnail: "", + description: "", + path: "", + searchText: [name].concat(domain.tags).join(' ').toUpperCase(), + online_users: domain.online_users + }, icb); } - var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity); - var filtered = !words.length ? suggestionChoices : allDomains.filter(function (domain) { - var text = domain.names.concat(domain.tags).join(' '); - if (domain.description) { - text += domain.description; + // IWBNI we could get these results in order with most-recent-entered first. + // In any case, we don't really need to preserve the domain.names order in the results. + asyncMap(domain.names, addPlace, cb); + } + + function suggestable(place) { + return (place.name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain. + && place.thumbnail + && place.online_users; // at least one present means it's actually online + } + function getDomainPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model + // Each page of results is processed completely before we start on the next page. + // For each page of domains, we process each domain in parallel, and for each domain, process each place name in parallel. + // This gives us minimum latency within the page, but we do preserve the order within the page by using asyncMap and + // only appending the collected results. + var params = [ + 'open', // published hours handle now + // FIXME: should determine if place is actually running + 'restriction=open', // Not by whitelist, etc. FIXME: If logged in, add hifi to the restriction options, in order to include places that require login. + // FIXME add maturity + 'protocol=' + encodeURIComponent(AddressManager.protocolVersion()), + 'sort_by=users', + 'sort_order=desc', + 'page=' + pageNumber + ]; + getRequest('https://metaverse.highfidelity.com/api/v1/domains/all?' + params.join('&'), function (error, data) { + if (handleError(error, data, cb)) { + return; } - text = text.toUpperCase(); - return words.every(function (word) { - return text.indexOf(word) >= 0; + asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) { + if (error) { + return cb(error); + } + // pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ] + pageResults.forEach(function (domainResults) { + allPlaces = allPlaces.concat(domainResults); + if (!addressLine.text) { // Don't add if the user is already filtering + domainResults.forEach(function (place) { + if (suggestable(place)) { + suggestions.append(place); + } + }); + } + }); + if (data.current_page < data.total_pages) { + return getDomainPage(pageNumber + 1, cb); + } + cb(); }); }); - for (var index in filtered) { fill1(index); } + } + function filterChoicesByText() { + suggestions.clear(); + var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity); + function matches(place) { + if (!words.length) { + return suggestable(place); + } + return words.every(function (word) { + return place.searchText.indexOf(word) >= 0; + }); + } + allPlaces.forEach(function (place) { + if (matches(place)) { + suggestions.append(place); + } + }); } function fillDestinations() { - allDomains = suggestionChoices = []; - getDomains({minUsers: 0, maxUsers: 20}, function (error, domains) { + allPlaces = []; + suggestions.clear(); + getDomainPage(1, function (error) { if (error) { console.log('domain query failed:', error); - return filterChoicesByText(); } - var here = AddressManager.hostname; // don't show where we are now. - allDomains = domains.filter(function (domain) { return domain.name !== here; }); - // Whittle down suggestions to those that have at least one user, and try to get pictures. - suggestionChoices = allDomains.filter(function (domain) { return true/*fixme hrs restore domain.online_users*/; }); - asyncEach(domains, addPictureToDomain, function (error) { - if (error) { - console.log('place picture query failed:', error); - } - // Whittle down more by requiring a picture. - // fixme hrs restore suggestionChoices = suggestionChoices.filter(function (domain) { return domain.lobby; }); - filterChoicesByText(); - }); + console.log('domain query finished', allPlaces.length); }); } From c3bf52267d4c57af4aa2b291cfc8ae6d8f33a894 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 1 Aug 2016 15:27:29 -0700 Subject: [PATCH 006/134] Don't suggest loaded places. --- interface/resources/qml/AddressBarDialog.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index b80ab579c8..9a8cfddc02 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -278,7 +278,8 @@ Window { function suggestable(place) { return (place.name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain. && place.thumbnail - && place.online_users; // at least one present means it's actually online + && place.online_users // at least one present means it's actually online + && place.online_users <= 20; } function getDomainPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model // Each page of results is processed completely before we start on the next page. From 1d7cdff2bcaf18e3d4835e063002dfd224936205 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 1 Aug 2016 13:24:22 -0700 Subject: [PATCH 007/134] Snapshot button plus script Minor change to allow snapshots to not notify (though the old way with CTRL+S still does). Added button to do it, saves them to disk. The plan is for us to add UI to share (or not) the snapshot. That's why we are not going through the notifications. Also, the script makes sure to hide/unhide hud and overlays. Next we will upload the pick to AWS via data-web (if you are logged in), and _then_ make the share UI. --- interface/src/Application.cpp | 6 +- interface/src/Application.h | 4 +- .../scripting/WindowScriptingInterface.cpp | 7 ++ .../src/scripting/WindowScriptingInterface.h | 3 +- scripts/system/assets/images/tools/snap.svg | 109 ++++++++++++++++++ scripts/system/notifications.js | 12 +- scripts/system/snapshot.js | 66 +++++++++++ 7 files changed, 196 insertions(+), 11 deletions(-) create mode 100755 scripts/system/assets/images/tools/snap.svg create mode 100644 scripts/system/snapshot.js diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e294ae38ad..abc0b91b2d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2281,7 +2281,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else if (isOption && !isShifted && !isMeta) { Menu::getInstance()->triggerOption(MenuOption::ScriptEditor); } else if (!isOption && !isShifted && isMeta) { - takeSnapshot(); + takeSnapshot(true); } break; @@ -5070,7 +5070,7 @@ void Application::toggleLogDialog() { } } -void Application::takeSnapshot() { +void Application::takeSnapshot(bool notify) { QMediaPlayer* player = new QMediaPlayer(); QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); @@ -5078,7 +5078,7 @@ void Application::takeSnapshot() { QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot()); - emit DependencyManager::get()->snapshotTaken(path); + emit DependencyManager::get()->snapshotTaken(path, notify); } float Application::getRenderResolutionScale() const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 0af65f665f..ea6a117cfa 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -247,6 +247,8 @@ public: float getAvatarSimrate() const { return _avatarSimCounter.rate(); } float getAverageSimsPerSecond() const { return _simCounter.rate(); } + + void takeSnapshot(bool notify); signals: void svoImportRequested(const QString& url); @@ -373,8 +375,6 @@ private: int sendNackPackets(); - void takeSnapshot(); - MyAvatar* getMyAvatar() const; void checkSkeleton() const; diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index b165cda135..fb7be86096 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -199,3 +199,10 @@ void WindowScriptingInterface::copyToClipboard(const QString& text) { qDebug() << "Copying"; QApplication::clipboard()->setText(text); } + +void WindowScriptingInterface::takeSnapshot(bool notify) { + // only evil-doers call takeSnapshot from a random thread + qApp->postLambdaEvent([&] { + qApp->takeSnapshot(notify); + }); +} diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 9d73111333..1abcb9db35 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -54,12 +54,13 @@ public slots: QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); void copyToClipboard(const QString& text); + void takeSnapshot(bool notify); signals: void domainChanged(const QString& domainHostname); void svoImportRequested(const QString& url); void domainConnectionRefused(const QString& reasonMessage, int reasonCode); - void snapshotTaken(const QString& path); + void snapshotTaken(const QString& path, bool notify); private slots: WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height); diff --git a/scripts/system/assets/images/tools/snap.svg b/scripts/system/assets/images/tools/snap.svg new file mode 100755 index 0000000000..c540f307ae --- /dev/null +++ b/scripts/system/assets/images/tools/snap.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 98a31d708c..34f9814d8a 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -527,12 +527,14 @@ function onDomainConnectionRefused(reason) { createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED); } -function onSnapshotTaken(path) { - var imageProperties = { - path: Script.resolvePath("file:///" + path), - aspectRatio: Window.innerWidth / Window.innerHeight +function onSnapshotTaken(path, notify) { + if (notify) { + var imageProperties = { + path: Script.resolvePath("file:///" + path), + aspectRatio: Window.innerWidth / Window.innerHeight + } + createNotification(wordWrap("Snapshot saved to " + path), NotificationType.SNAPSHOT, imageProperties); } - createNotification(wordWrap("Snapshot saved to " + path), NotificationType.SNAPSHOT, imageProperties); } // handles mouse clicks on buttons diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js new file mode 100644 index 0000000000..87ea3f29ec --- /dev/null +++ b/scripts/system/snapshot.js @@ -0,0 +1,66 @@ +// +// snapshot.js +// +// Created by David Kelly on 1 August 2016 +// Copyright 2016 High Fidelity, Inc +// +// Distributed under the Apache License, Version 2.0 +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +var SNAPSHOT_DELAY = 500; // 500ms +var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); +var resetOverlays; +var button = toolBar.addButton({ + objectName: "snapshot", + imageURL: Script.resolvePath("assets/images/tools/snap.svg"), + visible: true, + buttonState: 1, + defaultState: 1, + hoverState: 1, + alpha: 0.9, +}); + +function onClicked() { + // update button states + resetOverlays = Menu.isOptionChecked("Overlays"); + Window.snapshotTaken.connect(resetButtons); + + button.writeProperty("buttonState", 0); + button.writeProperty("defaultState", 0); + button.writeProperty("hoverState", 2); + + // hide overlays if they are on + if (resetOverlays) { + Menu.setIsOptionChecked("Overlays", false); + } + + // hide hud + toolBar.writeProperty("visible", false); + + // take snapshot (with no notification) + Script.setTimeout(function () { + Window.takeSnapshot(false); + }, SNAPSHOT_DELAY); +} + +function resetButtons(path, notify) { + // show overlays if they were on + if (resetOverlays) { + Menu.setIsOptionChecked("Overlays", true); + } + // show hud + toolBar.writeProperty("visible", true); + + // update button states + button.writeProperty("buttonState", 1); + button.writeProperty("defaultState", 1); + button.writeProperty("hoverState", 3); + Window.snapshotTaken.disconnect(resetButtons); +} + +button.clicked.connect(onClicked); + +Script.scriptEnding.connect(function () { + toolBar.removeButton("snapshot"); + button.clicked.disconnect(onClicked); +}); From fcd2947b19fbd50998fccfce979594e43d37b287 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 1 Aug 2016 18:37:22 -0700 Subject: [PATCH 008/134] Doh -- forgot to push this same logic as before to get a mono image in the HMD. --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index e0c87fbbed..a4db2811e0 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -662,10 +662,15 @@ void OpenGLDisplayPlugin::withMainThreadContext(std::function f) const { QImage OpenGLDisplayPlugin::getScreenshot() const { using namespace oglplus; - QImage screenshot(_compositeFramebuffer->size.x, _compositeFramebuffer->size.y, QImage::Format_RGBA8888); + auto width = _compositeFramebuffer->size.x; + if (isHmd()) { + width /= 2; + } + + QImage screenshot(width, _compositeFramebuffer->size.y, QImage::Format_RGBA8888); withMainThreadContext([&] { Framebuffer::Bind(Framebuffer::Target::Read, _compositeFramebuffer->fbo); - Context::ReadPixels(0, 0, _compositeFramebuffer->size.x, _compositeFramebuffer->size.y, enums::PixelDataFormat::RGBA, enums::PixelDataType::UnsignedByte, screenshot.bits()); + Context::ReadPixels(0, 0, width, _compositeFramebuffer->size.y, enums::PixelDataFormat::RGBA, enums::PixelDataType::UnsignedByte, screenshot.bits()); }); return screenshot.mirrored(false, true); } From 6e7b8282033a794285b5769119424eafee190cb9 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 2 Aug 2016 10:13:35 -0700 Subject: [PATCH 009/134] keep qml text fields up to date with vive virtual keyboard --- plugins/openvr/src/OpenVrHelpers.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index c93a2178b5..6f5c1b9511 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -170,8 +170,7 @@ void showOpenVrKeyboard(bool show = true) { } } -void finishOpenVrKeyboardInput() { - auto offscreenUi = DependencyManager::get(); +void updateFromOpenVrKeyboardInput() { auto chars = _overlay->GetKeyboardText(textArray, 8192); auto newText = QString(QByteArray(textArray, chars)); _keyboardFocusObject->setProperty("text", newText); @@ -181,6 +180,10 @@ void finishOpenVrKeyboardInput() { //QInputMethodEvent event(_existingText, QList()); //event.setCommitString(newText, 0, _existingText.size()); //qApp->sendEvent(_keyboardFocusObject, &event); +} +void finishOpenVrKeyboardInput() { + auto offscreenUi = DependencyManager::get(); + updateFromOpenVrKeyboardInput(); // Simulate an enter press on the top level window to trigger the action if (0 == (_currentHints & Qt::ImhMultiLine)) { qApp->sendEvent(offscreenUi->getWindow(), &QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::KeyboardModifiers(), QString("\n"))); @@ -261,6 +264,11 @@ void handleOpenVrEvents() { QMetaObject::invokeMethod(qApp, "quit"); break; + case vr::VREvent_KeyboardCharInput: + // Make the focused field match the keyboard results, inclusive of combining characters and such. + updateFromOpenVrKeyboardInput(); + break; + case vr::VREvent_KeyboardDone: finishOpenVrKeyboardInput(); From 70e07f329918ebf3883c217639dbd032eeec3234 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 2 Aug 2016 13:56:01 -0700 Subject: [PATCH 010/134] remove highlight move animation --- interface/resources/qml/AddressBarDialog.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 9a8cfddc02..b9e7941b76 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -83,6 +83,8 @@ Window { hoverThunk: function () { ListView.view.currentIndex = index; } unhoverThunk: function () { ListView.view.currentIndex = -1; } } + highlightMoveDuration: -1; + highlightMoveVelocity: -1; highlight: Rectangle { color: "transparent"; border.width: 2; border.color: "#1FA5E8"; z: 1; } } @@ -272,7 +274,7 @@ Window { } // IWBNI we could get these results in order with most-recent-entered first. // In any case, we don't really need to preserve the domain.names order in the results. - asyncMap(domain.names, addPlace, cb); + asyncMap(domain.names || [], addPlace, cb); } function suggestable(place) { From d34e72512bd4c6debee3957a715b3da7480b75e4 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 2 Aug 2016 15:13:48 -0700 Subject: [PATCH 011/134] Add snapshot.js to defaultScripts --- scripts/defaultScripts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 817d63582d..2e707d95ce 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -27,3 +27,4 @@ Script.load("system/controllers/grab.js"); Script.load("system/controllers/teleport.js"); Script.load("system/dialTone.js"); Script.load("system/firstPersonHMD.js"); +Script.load("system/snapshot.js"); From e593077b4baa5ce1879d68bacaf702dc7532ff6c Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 3 Aug 2016 09:39:27 -0700 Subject: [PATCH 012/134] basic display of user story feed (hardcoded switch place names vs feed) --- interface/resources/qml/AddressBarDialog.qml | 130 ++++++++++++++----- 1 file changed, 101 insertions(+), 29 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index b9e7941b76..df6a5837ac 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -49,9 +49,31 @@ Window { addressLine.text = card.path; toggleOrGo(true); } + property bool useFeed: false; property var allPlaces: []; + property var allStories: []; property int cardWidth: 200; property int cardHeight: 152; + function pastTime(timestamp) { // Answer a descriptive string + timestamp = new Date(timestamp); + var then = timestamp.getTime(), + now = Date.now(), + since = now - then, + ONE_MINUTE = 1000 * 60, + ONE_HOUR = ONE_MINUTE * 60, + hours = since / ONE_HOUR, + minutes = (hours % 1) * 60; + if (hours > 24) { + return timestamp.toDateString(); + } + if (hours > 1) { + return Math.floor(hours).toString() + ' hr ' + Math.floor(minutes) + ' min ago'; + } + if (minutes >= 2) { + return Math.floor(minutes).toString() + ' min ago'; + } + return 'about a minute ago'; + } AddressBarDialog { id: addressBarDialog @@ -76,10 +98,10 @@ Window { width: cardWidth; height: cardHeight; goFunction: goCard; - path: model.name + model.path; - thumbnail: model.thumbnail; - placeText: model.name; - usersText: model.online_users + ((model.online_users === 1) ? ' person' : ' people'); + path: model.place_name + model.path; + thumbnail: model.thumbnail_url; + placeText: model.place_name; + usersText: (model.created_at ? pastTime(model.created_at) : (model.online_users + ((model.online_users === 1) ? ' person' : ' people'))); hoverThunk: function () { ListView.view.currentIndex = index; } unhoverThunk: function () { ListView.view.currentIndex = -1; } } @@ -235,23 +257,31 @@ Window { return x; } - function handleError(error, data, cb) { // cb(error) and answer truthy if needed, else falsey + function handleError(url, error, data, cb) { // cb(error) and answer truthy if needed, else falsey if (!error && (data.status === 'success')) { return; } - cb(error || new Error(data.status + ': ' + data.error)); + if (!error) { // Create a message from the data + error = data.status + ': ' + data.error; + } + if (typeof(error) === 'string') { // Make a proper Error object + error = new Error(error); + } + error.message += ' in ' + url; // Include the url. + cb(error); return true; } function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description - getRequest('https://metaverse.highfidelity.com/api/v1/places/' + placeData.name, function (error, data) { - if (handleError(error, data, cb)) { + var url = 'https://metaverse.highfidelity.com/api/v1/places/' + placeData.place_name; + getRequest(url, function (error, data) { + if (handleError(url, error, data, cb)) { return; } var place = data.data.place, previews = place.previews; placeData.path = place.path; if (previews && previews.thumbnail) { - placeData.thumbnail = previews.thumbnail; + placeData.thumbnail_url = previews.thumbnail; } if (place.description) { placeData.description = place.description; @@ -260,17 +290,28 @@ Window { cb(error, placeData); }); } + function makeModelData(data, optionalPlaceName) { // create a new obj from data + // ListModel elements will only ever have those properties that are defined by the first obj that is added. + // So here we make sure that we have all the properties we need, regardless of whether it is a place data or user story. + var name = optionalPlaceName || data.place_name, + tags = data.tags || [data.action], + description = data.description || ""; + return { + place_name: name, + path: data.path || "", + created_at: data.create_at || "8/3/2016", + thumbnail_url: data.thumbnail_url || "", + + tags: tags, + description: description, + online_users: data.online_users, + + searchText: [name].concat(tags, description).join(' ').toUpperCase() + } + } function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData) function addPlace(name, icb) { - getPlace({ - name: name, - tags: domain.tags, - thumbnail: "", - description: "", - path: "", - searchText: [name].concat(domain.tags).join(' ').toUpperCase(), - online_users: domain.online_users - }, icb); + getPlace(makeModelData(domain, name), icb); } // IWBNI we could get these results in order with most-recent-entered first. // In any case, we don't really need to preserve the domain.names order in the results. @@ -278,8 +319,11 @@ Window { } function suggestable(place) { - return (place.name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain. - && place.thumbnail + if (useFeed) { + return true; + } + return (place.place_name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain. + && place.thumbnail_url && place.online_users // at least one present means it's actually online && place.online_users <= 20; } @@ -298,8 +342,9 @@ Window { 'sort_order=desc', 'page=' + pageNumber ]; - getRequest('https://metaverse.highfidelity.com/api/v1/domains/all?' + params.join('&'), function (error, data) { - if (handleError(error, data, cb)) { + var url = 'https://metaverse.highfidelity.com/api/v1/domains/all?' + params.join('&'); + getRequest(url, function (error, data) { + if (handleError(url, error, data, cb)) { return; } asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) { @@ -309,7 +354,7 @@ Window { // pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ] pageResults.forEach(function (domainResults) { allPlaces = allPlaces.concat(domainResults); - if (!addressLine.text) { // Don't add if the user is already filtering + if (!addressLine.text && !useFeed) { // Don't add if the user is already filtering domainResults.forEach(function (place) { if (suggestable(place)) { suggestions.append(place); @@ -324,9 +369,35 @@ Window { }); }); } + function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model + var url = 'https://metaverse.highfidelity.com/api/v1/user_stories?page=' + pageNumber; + getRequest(url, function (error, data) { + if (handleError(url, error, data, cb)) { + return; + } + // FIXME: For debugging until we have real data + data = {user_stories: [ + {created_at: "8/3/2016", action: "snapshot", path: "/4257.1,126.084,1335.45/0,-0.857368,0,0.514705", place_name: "SpiritMoving", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/c28/a26/f0-/thumbnail/hifi-place-c28a26f0-6991-4654-9c2b-e64228c06954.jpg?1456878797"}, + {created_at: "8/3/2016", action: "snapshot", path: "/10077.4,4003.6,9972.56/0,-0.410351,0,0.911928", place_name: "Ventura", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/1f5/e6b/00-/thumbnail/hifi-place-1f5e6b00-2bf0-4319-b9ae-a2344a72354c.png?1454321596"} + ]}; + + var stories = data.user_stories.map(makeModelData); + allStories = allStories.concat(stories); + if (!addressLine.text && useFeed) { // Don't add if the user is already filtering + stories.forEach(function (story) { + suggestions.append(story); + }); + } + if (data.current_page < data.total_pages) { + return getUserStoryPage(pageNumber + 1, cb); + } + cb(); + }); + } function filterChoicesByText() { suggestions.clear(); - var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity); + var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity), + data = useFeed ? allStories : allPlaces; function matches(place) { if (!words.length) { return suggestable(place); @@ -335,7 +406,7 @@ Window { return place.searchText.indexOf(word) >= 0; }); } - allPlaces.forEach(function (place) { + data.forEach(function (place) { if (matches(place)) { suggestions.append(place); } @@ -344,12 +415,13 @@ Window { function fillDestinations() { allPlaces = []; + allStories = []; suggestions.clear(); getDomainPage(1, function (error) { - if (error) { - console.log('domain query failed:', error); - } - console.log('domain query finished', allPlaces.length); + console.log('domain query', error, allPlaces.length); + }); + getUserStoryPage(1, function (error) { + console.log('user stories query', error, allStories.length); }); } From 188e525efcdea070d2b227be4ae09abc2b918538 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 3 Aug 2016 11:48:58 -0700 Subject: [PATCH 013/134] basic ugly feed/places toggle button --- interface/resources/qml/AddressBarDialog.qml | 21 ++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index df6a5837ac..de2e16ddfc 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -193,7 +193,24 @@ Window { helperText: "Go to: place, @user, /path, network address" onTextChanged: filterChoicesByText() } - + Rectangle { + color: "red"; + height: addressLine.height; + width: addressLine.height; + anchors { + left: addressLine.right; + bottom: addressLine.bottom; + } + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton + onClicked: { + console.log('fixme hrs toggle'); + useFeed = !useFeed; + filterChoicesByText(); + } + } + } } } @@ -299,7 +316,7 @@ Window { return { place_name: name, path: data.path || "", - created_at: data.create_at || "8/3/2016", + created_at: data.create_at || "", thumbnail_url: data.thumbnail_url || "", tags: tags, From 30327d81357316a5880cae84b2af3f241f08924f Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 3 Aug 2016 16:02:22 -0700 Subject: [PATCH 014/134] New buttons, with hover behavior. Also don't impose test data if the api gives data. --- interface/resources/images/backward.svg | 28 ++++ interface/resources/images/forward.svg | 28 ++++ interface/resources/images/home.svg | 46 +++++++ interface/resources/images/places.svg | 33 +++++ interface/resources/images/snap-feed.svg | 41 ++++++ interface/resources/qml/AddressBarDialog.qml | 131 ++++++++++--------- 6 files changed, 242 insertions(+), 65 deletions(-) create mode 100644 interface/resources/images/backward.svg create mode 100644 interface/resources/images/forward.svg create mode 100644 interface/resources/images/home.svg create mode 100644 interface/resources/images/places.svg create mode 100644 interface/resources/images/snap-feed.svg diff --git a/interface/resources/images/backward.svg b/interface/resources/images/backward.svg new file mode 100644 index 0000000000..9d36778aa3 --- /dev/null +++ b/interface/resources/images/backward.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + diff --git a/interface/resources/images/forward.svg b/interface/resources/images/forward.svg new file mode 100644 index 0000000000..65ec62f947 --- /dev/null +++ b/interface/resources/images/forward.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + diff --git a/interface/resources/images/home.svg b/interface/resources/images/home.svg new file mode 100644 index 0000000000..1e201a1a9d --- /dev/null +++ b/interface/resources/images/home.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + diff --git a/interface/resources/images/places.svg b/interface/resources/images/places.svg new file mode 100644 index 0000000000..6336ab111f --- /dev/null +++ b/interface/resources/images/places.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + diff --git a/interface/resources/images/snap-feed.svg b/interface/resources/images/snap-feed.svg new file mode 100644 index 0000000000..3eae156cd6 --- /dev/null +++ b/interface/resources/images/snap-feed.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index de2e16ddfc..5a92360488 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -14,6 +14,7 @@ import "controls" import "styles" import "windows" import "hifi" +import "hifi/toolbars" Window { id: root @@ -118,64 +119,43 @@ Window { property int inputAreaHeight: 56.0 * root.scale // Height of the background's input area property int inputAreaStep: (height - inputAreaHeight) / 2 - Image { + ToolbarButton { id: homeButton - source: "../images/home-button.svg" - width: 29 - height: 26 + imageURL: "../images/home.svg" + buttonState: 1 + defaultState: 1 + hoverState: 2 + onClicked: addressBarDialog.loadHome(); anchors { left: parent.left - leftMargin: parent.height + 2 * hifi.layout.spacing + leftMargin: parent.height verticalCenter: parent.verticalCenter } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.LeftButton - onClicked: { - addressBarDialog.loadHome() - } - } } - Image { - id: backArrow - source: addressBarDialog.backEnabled ? "../images/left-arrow.svg" : "../images/left-arrow-disabled.svg" - width: 22 - height: 26 + ToolbarButton { + id: backArrow; + imageURL: "../images/backward.svg"; + hoverState: addressBarDialog.backEnabled ? 2 : 0; + defaultState: addressBarDialog.backEnabled ? 1 : 0; + buttonState: addressBarDialog.backEnabled ? 1 : 0; // fixme: needs work + onClicked: addressBarDialog.loadBack(); anchors { left: homeButton.right - leftMargin: 2 * hifi.layout.spacing verticalCenter: parent.verticalCenter } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.LeftButton - onClicked: { - addressBarDialog.loadBack() - } - } } - - Image { - id: forwardArrow - source: addressBarDialog.forwardEnabled ? "../images/right-arrow.svg" : "../images/right-arrow-disabled.svg" - width: 22 - height: 26 + ToolbarButton { + id: forwardArrow; + imageURL: "../images/forward.svg"; + hoverState: addressBarDialog.forwardEnabled ? 2 : 0; + defaultState: addressBarDialog.forwardEnabled ? 1 : 0; + buttonState: addressBarDialog.forwardEnabled ? 1 : 0; // fixme: needs work + onClicked: addressBarDialog.loadForward(); anchors { left: backArrow.right - leftMargin: 2 * hifi.layout.spacing verticalCenter: parent.verticalCenter } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.LeftButton - onClicked: { - addressBarDialog.loadForward() - } - } } // FIXME replace with TextField @@ -183,37 +163,54 @@ Window { id: addressLine focus: true anchors { - fill: parent + top: parent.top + left: parent.left + bottom: parent.bottom + right: placesButton.left leftMargin: parent.height + parent.height + hifi.layout.spacing * 7 - rightMargin: hifi.layout.spacing * 2 + rightMargin: hifi.layout.spacing topMargin: parent.inputAreaStep + hifi.layout.spacing bottomMargin: parent.inputAreaStep + hifi.layout.spacing } font.pixelSize: hifi.fonts.pixelSize * root.scale * 0.75 - helperText: "Go to: place, @user, /path, network address" + helperText: "Go to: place, @user, /path" //, network address" onTextChanged: filterChoicesByText() } - Rectangle { - color: "red"; - height: addressLine.height; - width: addressLine.height; + // These two are radio buttons. + ToolbarButton { + id: placesButton + imageURL: "../images/places.svg" + buttonState: 1 + defaultState: useFeed ? 0 : 1; + hoverState: useFeed ? 2 : -1; + onClicked: useFeed ? toggleFeed() : identity() anchors { - left: addressLine.right; + right: feedButton.left; bottom: addressLine.bottom; } - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.LeftButton - onClicked: { - console.log('fixme hrs toggle'); - useFeed = !useFeed; - filterChoicesByText(); - } + } + ToolbarButton { + id: feedButton; + imageURL: "../images/snap-feed.svg"; + buttonState: 0 + defaultState: useFeed ? 1 : 0; + hoverState: useFeed ? -1 : 2; + onClicked: useFeed ? identity() : toggleFeed(); + anchors { + right: parent.right; + bottom: addressLine.bottom; + rightMargin: hifi.layout.spacing; } } } } + function toggleFeed () { + useFeed = !useFeed; + placesButton.buttonState = useFeed ? 0 : 1; + feedButton.buttonState = useFeed ? 1 : 0; + filterChoicesByText(); + } function getRequest(url, cb) { // cb(error, responseOfCorrectContentType) of url. General for 'get' text/html/json, but without redirects. // TODO: make available to other .qml. var request = new XMLHttpRequest(); @@ -393,12 +390,16 @@ Window { return; } // FIXME: For debugging until we have real data - data = {user_stories: [ - {created_at: "8/3/2016", action: "snapshot", path: "/4257.1,126.084,1335.45/0,-0.857368,0,0.514705", place_name: "SpiritMoving", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/c28/a26/f0-/thumbnail/hifi-place-c28a26f0-6991-4654-9c2b-e64228c06954.jpg?1456878797"}, - {created_at: "8/3/2016", action: "snapshot", path: "/10077.4,4003.6,9972.56/0,-0.410351,0,0.911928", place_name: "Ventura", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/1f5/e6b/00-/thumbnail/hifi-place-1f5e6b00-2bf0-4319-b9ae-a2344a72354c.png?1454321596"} - ]}; + if (!data.user_stories.length) { + data.user_stories = [ + {created_at: "8/3/2016", action: "snapshot", path: "/4257.1,126.084,1335.45/0,-0.857368,0,0.514705", place_name: "SpiritMoving", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/c28/a26/f0-/thumbnail/hifi-place-c28a26f0-6991-4654-9c2b-e64228c06954.jpg?1456878797"}, + {created_at: "8/3/2016", action: "snapshot", path: "/10077.4,4003.6,9972.56/0,-0.410351,0,0.911928", place_name: "Ventura", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/1f5/e6b/00-/thumbnail/hifi-place-1f5e6b00-2bf0-4319-b9ae-a2344a72354c.png?1454321596"} + ]; + } - var stories = data.user_stories.map(makeModelData); + var stories = data.user_stories.map(function (story) { // explicit single-argument function + return makeModelData(story); + }); allStories = allStories.concat(stories); if (!addressLine.text && useFeed) { // Don't add if the user is already filtering stories.forEach(function (story) { @@ -435,10 +436,10 @@ Window { allStories = []; suggestions.clear(); getDomainPage(1, function (error) { - console.log('domain query', error, allPlaces.length); + console.log('domain query', error || 'ok', allPlaces.length); }); getUserStoryPage(1, function (error) { - console.log('user stories query', error, allStories.length); + console.log('user stories query', error || 'ok', allStories.length); }); } From 8c6744e5e8308d4a212bf304b8332b9c347b450a Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 3 Aug 2016 16:18:41 -0700 Subject: [PATCH 015/134] new address bar graphic --- interface/resources/images/address-bar.svg | 97 ++++---------------- interface/resources/qml/AddressBarDialog.qml | 9 +- 2 files changed, 22 insertions(+), 84 deletions(-) diff --git a/interface/resources/images/address-bar.svg b/interface/resources/images/address-bar.svg index 56dc4f028c..76ad7c0547 100644 --- a/interface/resources/images/address-bar.svg +++ b/interface/resources/images/address-bar.svg @@ -1,81 +1,18 @@ - - - - - - image/svg+xml - - - - - - - - - - - + + + + + + + diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 5a92360488..0ae4d6d9ff 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -128,7 +128,7 @@ Window { onClicked: addressBarDialog.loadHome(); anchors { left: parent.left - leftMargin: parent.height + leftMargin: hifi.layout.spacing * 2 verticalCenter: parent.verticalCenter } } @@ -164,10 +164,10 @@ Window { focus: true anchors { top: parent.top - left: parent.left bottom: parent.bottom + left: forwardArrow.right right: placesButton.left - leftMargin: parent.height + parent.height + hifi.layout.spacing * 7 + leftMargin: hifi.layout.spacing * 4 rightMargin: hifi.layout.spacing topMargin: parent.inputAreaStep + hifi.layout.spacing bottomMargin: parent.inputAreaStep + hifi.layout.spacing @@ -186,6 +186,7 @@ Window { onClicked: useFeed ? toggleFeed() : identity() anchors { right: feedButton.left; + rightMargin: hifi.layout.spacing * 3; bottom: addressLine.bottom; } } @@ -199,7 +200,7 @@ Window { anchors { right: parent.right; bottom: addressLine.bottom; - rightMargin: hifi.layout.spacing; + rightMargin: hifi.layout.spacing * 3; } } } From 4d0c5c5d19cc9febe1e456e0d306976056c47a1b Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 3 Aug 2016 16:22:46 -0700 Subject: [PATCH 016/134] fix snapshot button hover --- scripts/system/snapshot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 87ea3f29ec..280bd3b5d0 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -16,7 +16,7 @@ var button = toolBar.addButton({ visible: true, buttonState: 1, defaultState: 1, - hoverState: 1, + hoverState: 2, alpha: 0.9, }); From c44ce0f5b59ad3f9249110f7def4fc8322a46723 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 3 Aug 2016 17:03:27 -0700 Subject: [PATCH 017/134] Fix forward/back button states. --- interface/resources/qml/AddressBarDialog.qml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 0ae4d6d9ff..fe44607b53 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -80,6 +80,9 @@ Window { id: addressBarDialog implicitWidth: backgroundImage.width implicitHeight: backgroundImage.height + // The buttons have their button state changed on hover, so we have to manually fix them up here + onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0; + onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0; ListModel { id: suggestions } @@ -138,7 +141,7 @@ Window { imageURL: "../images/backward.svg"; hoverState: addressBarDialog.backEnabled ? 2 : 0; defaultState: addressBarDialog.backEnabled ? 1 : 0; - buttonState: addressBarDialog.backEnabled ? 1 : 0; // fixme: needs work + buttonState: addressBarDialog.backEnabled ? 1 : 0; onClicked: addressBarDialog.loadBack(); anchors { left: homeButton.right @@ -150,7 +153,7 @@ Window { imageURL: "../images/forward.svg"; hoverState: addressBarDialog.forwardEnabled ? 2 : 0; defaultState: addressBarDialog.forwardEnabled ? 1 : 0; - buttonState: addressBarDialog.forwardEnabled ? 1 : 0; // fixme: needs work + buttonState: addressBarDialog.forwardEnabled ? 1 : 0; onClicked: addressBarDialog.loadForward(); anchors { left: backArrow.right From 421707c5d84aaac954309b2945822aa51ea7042e Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 4 Aug 2016 10:07:33 -0700 Subject: [PATCH 018/134] fix typo that was making user stories not show date --- interface/resources/qml/AddressBarDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index fe44607b53..fd2abd01f5 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -317,7 +317,7 @@ Window { return { place_name: name, path: data.path || "", - created_at: data.create_at || "", + created_at: data.created_at || "", thumbnail_url: data.thumbnail_url || "", tags: tags, From d39446f340157e3bb4ed1b666219d3d39217c367 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 4 Aug 2016 10:36:17 -0700 Subject: [PATCH 019/134] no place name over user-story scroll items --- interface/resources/qml/AddressBarDialog.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index fd2abd01f5..0c6288c828 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -104,8 +104,8 @@ Window { goFunction: goCard; path: model.place_name + model.path; thumbnail: model.thumbnail_url; - placeText: model.place_name; - usersText: (model.created_at ? pastTime(model.created_at) : (model.online_users + ((model.online_users === 1) ? ' person' : ' people'))); + placeText: model.created_at ? "" : model.place_name; + usersText: model.created_at ? pastTime(model.created_at) : (model.online_users + ((model.online_users === 1) ? ' person' : ' people')); hoverThunk: function () { ListView.view.currentIndex = index; } unhoverThunk: function () { ListView.view.currentIndex = -1; } } From f5d07f418679df39140ed9b9dffd11eef53928f3 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 4 Aug 2016 11:55:31 -0700 Subject: [PATCH 020/134] helper text size and italic --- interface/resources/qml/AddressBarDialog.qml | 4 +++- interface/resources/qml/controls/TextInput.qml | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 0c6288c828..29cba76f1d 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -176,7 +176,9 @@ Window { bottomMargin: parent.inputAreaStep + hifi.layout.spacing } font.pixelSize: hifi.fonts.pixelSize * root.scale * 0.75 - helperText: "Go to: place, @user, /path" //, network address" + helperText: "Go to: place, @user, /path, network address" + helperPixelSize: font.pixelSize * 0.75 + helperItalic: true onTextChanged: filterChoicesByText() } // These two are radio buttons. diff --git a/interface/resources/qml/controls/TextInput.qml b/interface/resources/qml/controls/TextInput.qml index b7ca6d2c1b..77e11177e1 100644 --- a/interface/resources/qml/controls/TextInput.qml +++ b/interface/resources/qml/controls/TextInput.qml @@ -12,6 +12,8 @@ Original.TextInput { verticalAlignment: Original.TextInput.AlignVCenter font.family: hifi.fonts.fontFamily font.pixelSize: hifi.fonts.pixelSize + property int helperPixelSize: font.pixelSize + property bool helperItalic: false /* Original.Rectangle { @@ -23,7 +25,8 @@ Original.TextInput { */ Text { anchors.fill: parent - font.pixelSize: parent.font.pixelSize + font.pixelSize: helperPixelSize + font.italic: helperItalic font.family: parent.font.family verticalAlignment: parent.verticalAlignment horizontalAlignment: parent.horizontalAlignment From 1ecb01feacea805d41f8ce39db9d47f00b785576 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 4 Aug 2016 12:06:07 -0700 Subject: [PATCH 021/134] center the scroll --- interface/resources/qml/AddressBarDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 29cba76f1d..3e676b7340 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -94,7 +94,7 @@ Window { anchors { bottom: backgroundImage.top; bottomMargin: 2 * hifi.layout.spacing; - right: backgroundImage.right; + horizontalCenter: backgroundImage.horizontalCenter } model: suggestions; orientation: ListView.Horizontal; From 04bd98b15ffd9a7f73966bd543a5896179eafffc Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 4 Aug 2016 12:33:50 -0700 Subject: [PATCH 022/134] new assets. remove margins between buttons (letting the graphics do the work) --- interface/resources/images/address-bar.svg | 12 ++-- interface/resources/images/backward.svg | 26 ++++---- interface/resources/images/forward.svg | 26 ++++---- interface/resources/images/home.svg | 62 +++++++++++--------- interface/resources/images/places.svg | 36 ++++++------ interface/resources/images/snap-feed.svg | 48 +++++++-------- interface/resources/qml/AddressBarDialog.qml | 9 ++- 7 files changed, 111 insertions(+), 108 deletions(-) diff --git a/interface/resources/images/address-bar.svg b/interface/resources/images/address-bar.svg index 76ad7c0547..a8cb158492 100644 --- a/interface/resources/images/address-bar.svg +++ b/interface/resources/images/address-bar.svg @@ -9,10 +9,10 @@ .st1{fill:#E6E7E8;} .st2{fill:#FFFFFF;} - - - + + + diff --git a/interface/resources/images/backward.svg b/interface/resources/images/backward.svg index 9d36778aa3..e4502fa80e 100644 --- a/interface/resources/images/backward.svg +++ b/interface/resources/images/backward.svg @@ -9,19 +9,19 @@ .st3{fill:#31D8FF;} - - - - + + + + diff --git a/interface/resources/images/forward.svg b/interface/resources/images/forward.svg index 65ec62f947..0c5cbe3d0c 100644 --- a/interface/resources/images/forward.svg +++ b/interface/resources/images/forward.svg @@ -9,19 +9,19 @@ .st3{fill:#31D8FF;} - - - - + + + + diff --git a/interface/resources/images/home.svg b/interface/resources/images/home.svg index 1e201a1a9d..7740dc9568 100644 --- a/interface/resources/images/home.svg +++ b/interface/resources/images/home.svg @@ -9,37 +9,41 @@ .st3{fill:#31D8FF;} - - - - - - + + - - + + + + + + + + + + diff --git a/interface/resources/images/places.svg b/interface/resources/images/places.svg index 6336ab111f..f70695d606 100644 --- a/interface/resources/images/places.svg +++ b/interface/resources/images/places.svg @@ -9,24 +9,24 @@ .st3{fill:#31D8FF;} - - - - - - - + + + + + + + diff --git a/interface/resources/images/snap-feed.svg b/interface/resources/images/snap-feed.svg index 3eae156cd6..c2dede6e0f 100644 --- a/interface/resources/images/snap-feed.svg +++ b/interface/resources/images/snap-feed.svg @@ -9,31 +9,31 @@ .st3{fill:#31D8FF;} - - - - - - - - + + + + + + + + - - + + diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 3e676b7340..7eb4de6bba 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -131,7 +131,7 @@ Window { onClicked: addressBarDialog.loadHome(); anchors { left: parent.left - leftMargin: hifi.layout.spacing * 2 + leftMargin: homeButton.width / 2 verticalCenter: parent.verticalCenter } } @@ -170,8 +170,8 @@ Window { bottom: parent.bottom left: forwardArrow.right right: placesButton.left - leftMargin: hifi.layout.spacing * 4 - rightMargin: hifi.layout.spacing + leftMargin: forwardArrow.width + rightMargin: placesButton.width topMargin: parent.inputAreaStep + hifi.layout.spacing bottomMargin: parent.inputAreaStep + hifi.layout.spacing } @@ -191,7 +191,6 @@ Window { onClicked: useFeed ? toggleFeed() : identity() anchors { right: feedButton.left; - rightMargin: hifi.layout.spacing * 3; bottom: addressLine.bottom; } } @@ -205,7 +204,7 @@ Window { anchors { right: parent.right; bottom: addressLine.bottom; - rightMargin: hifi.layout.spacing * 3; + rightMargin: feedButton.width / 2 } } } From 8a7bbbaaed84921548f4cfb8a8fbc45ca8b416ac Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 4 Aug 2016 12:37:09 -0700 Subject: [PATCH 023/134] limit user stories to first 100 --- interface/resources/qml/AddressBarDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 7eb4de6bba..5883872c95 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -411,7 +411,7 @@ Window { suggestions.append(story); }); } - if (data.current_page < data.total_pages) { + if ((data.current_page < data.total_pages) && (data.current_page <= 10)) { // just 10 pages = 100 stories for now return getUserStoryPage(pageNumber + 1, cb); } cb(); From fed775ff83b5211350931a2be98f8623aa622db0 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 4 Aug 2016 15:52:39 -0700 Subject: [PATCH 024/134] simple snapshot confirmation --- interface/src/scripting/WindowScriptingInterface.cpp | 2 +- scripts/system/snapshot.js | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index fb7be86096..026818ec82 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -96,7 +96,7 @@ void WindowScriptingInterface::alert(const QString& message) { /// \param const QString& message message to display /// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwise QScriptValue WindowScriptingInterface::confirm(const QString& message) { - return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message))); + return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No))); } /// Display a prompt with a text box diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 87ea3f29ec..92ce36e935 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -20,6 +20,13 @@ var button = toolBar.addButton({ alpha: 0.9, }); +function confirmShare(data) { + if (!Window.confirm("Share snapshot " + data.localPath + "?")) { // This dialog will be more elaborate... + return; + } + Window.alert("Pretending to upload. That code will go here."); +} + function onClicked() { // update button states resetOverlays = Menu.isOptionChecked("Overlays"); @@ -56,7 +63,8 @@ function resetButtons(path, notify) { button.writeProperty("defaultState", 1); button.writeProperty("hoverState", 3); Window.snapshotTaken.disconnect(resetButtons); -} + confirmShare({localPath: path}); + } button.clicked.connect(onClicked); From 4f33e1502f19835460b007891c33c13dd2d6b90f Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Mon, 27 Jun 2016 17:41:21 -0700 Subject: [PATCH 025/134] starting the zip project --- interface/src/Application.cpp | 7 +++++++ .../src/scripting/WindowScriptingInterface.cpp | 13 +++++++++++++ scripts/system/edit.js | 13 +++++++++++++ 3 files changed, 33 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5d50a1c9fe..08788cb5bc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2015,6 +2015,13 @@ bool Application::importSVOFromURL(const QString& urlString) { return true; } +// attempt to start ZIP download project +bool Appplication::importZIPFromURL(const QString& urlString) { + emit zipImportRequested(urlString); + return true; +} +// end attempt + bool Application::event(QEvent* event) { if (!Menu::getInstance()) { diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index b165cda135..4a4f4b1025 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -59,6 +59,19 @@ WindowScriptingInterface::WindowScriptingInterface() { OffscreenUi::warning("Import SVO Error", "You need to be running edit.js to import entities."); } }); + // attempt to start ZIP download project + connect(qApp, &Application::zipImportRequested, [this](const QString& urlString) { + static const QMetaMethod zipImportRequestedSignal = + QMetaMethod::fromSignal(&WindowScriptingInterface::zipImportRequested); + + if (isSignalConnected(zipImportRequestedSignal)) { + QUrl url(urlString); + emit zipImportRequested(url.url()); + } else { + OffscreenUi::warning("Import ZIP Error", "You need to be running edit.js to import entities."); + } + // end attempt + }); } WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) { diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 25c25a9a7e..18a76eb45f 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1205,6 +1205,19 @@ function importSVO(importURL) { } Window.svoImportRequested.connect(importSVO); +// attempt to start ZIP download project +function importZIP(importURL) { + print("Import ZIP requested: " + importURL); + if (!Entities.canAdjustLocks()) { + Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); + return; + } + + +} +Window.zipImportRequested.connect(importZIP); +//end attempt + Menu.menuItemEvent.connect(handeMenuEvent); Controller.keyPressEvent.connect(function (event) { From f277a019bff5aadf8f8b809cd8b3eb44d28dd821 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Tue, 28 Jun 2016 17:56:28 -0700 Subject: [PATCH 026/134] FileScriptingInterface Created new .cpp and .h for the download and unzipping of a model --- .../src/scripting/WindowScriptingInterface.h | 1 + .../src/FileScriptingInterface.cpp | 51 +++++++++++++++++++ .../src/FileScriptingInterface.h | 30 +++++++++++ libraries/script-engine/src/ScriptEngine.cpp | 5 ++ 4 files changed, 87 insertions(+) create mode 100644 libraries/script-engine/src/FileScriptingInterface.cpp create mode 100644 libraries/script-engine/src/FileScriptingInterface.h diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 9d73111333..b33da4ef4d 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -58,6 +58,7 @@ public slots: signals: void domainChanged(const QString& domainHostname); void svoImportRequested(const QString& url); + void zipImportRequested(const QString& url); // zip project void domainConnectionRefused(const QString& reasonMessage, int reasonCode); void snapshotTaken(const QString& path); diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp new file mode 100644 index 0000000000..3ecb1bfd22 --- /dev/null +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -0,0 +1,51 @@ +// +// FileScriptingInterface.cpp +// interface/src/scripting +// +// Created by Elisa Lupin-Jimenez on 6/28/16. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include +#include "ResourceManager.h" + +#include "FileScriptingInterface.h" + + +FileScriptingInterface::FileScriptingInterface(QObject* parent) { + // nothing for now +} + +void FileScriptingInterface::downloadZip() { + QUrl url(*parent); + auto request = ResourceManager::createResourceRequest(nullptr, url); + connect(request, &ResourceRequest::finished, this, &FileScriptingInterface::unzipFile); + request->send(); +} + +// clement's help :D +bool FileScriptingInterface::unzipFile() { + ResourceRequest* request = qobject_cast(sender()); + + // Get the file URL + QUrl url = request->getUrl(); + + if (request->getResult() == ResourceRequest::Success) { + qDebug() << "Success =)"; + + QByteArray fileContent = request->getData(); // <-- Downloaded file is in here + // Do stuff + // + // unzipFile(fileContent); + + } else { + qDebug() << "Could not download the file =("; + } + +} + diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h new file mode 100644 index 0000000000..67ea207aba --- /dev/null +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -0,0 +1,30 @@ +// +// FileScriptingInterface.h +// interface/src/scripting +// +// Created by Elisa Lupin-Jimenez on 6/28/16. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_FileScriptingInterface_h +#define hifi_FileScriptingInterface_h + +#include + +class FileScriptingInterface : public QObject { + Q_OBJECT + +public: + FileScriptingInterface(QObject* parent); + +public slots: + QScriptValue hasFocus(); + +}; + + + +#endif // hifi_FileScriptingInterface_h \ No newline at end of file diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index f98b07478b..fe7e1c4036 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -49,6 +49,7 @@ #include "BatchLoader.h" #include "DataViewClass.h" #include "EventTypes.h" +#include "FileScriptingInterface.h" // unzip project #include "MenuItemProperties.h" #include "ScriptAudioInjector.h" #include "ScriptCache.h" @@ -501,6 +502,10 @@ void ScriptEngine::init() { registerGlobalObject("Mat4", &_mat4Library); registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("Messages", DependencyManager::get().data()); + + // unzip project + registerGlobalObject("File", new FileScriptingInterface(this)); + qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue); qScriptRegisterMetaType(this, resultHandlerToScriptValue, resultHandlerFromScriptValue); From 0e79aa9dbe6b132cd57e26b6355a97975a2b2e82 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Wed, 29 Jun 2016 18:10:51 -0700 Subject: [PATCH 027/134] Added quazip for unzipping functions --- BUILD.md | 1 + CMakeLists.txt | 1 + libraries/script-engine/CMakeLists.txt | 6 ++ .../src/FileScriptingInterface.cpp | 85 ++++++++++++++++--- .../src/FileScriptingInterface.h | 11 ++- 5 files changed, 89 insertions(+), 15 deletions(-) diff --git a/BUILD.md b/BUILD.md index c1ccd3193e..4ff45a0b1e 100644 --- a/BUILD.md +++ b/BUILD.md @@ -5,6 +5,7 @@ * [OpenSSL](https://www.openssl.org/community/binaries.html) ~> 1.0.1m * IMPORTANT: Using the recommended version of OpenSSL is critical to avoid security vulnerabilities. * [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional) +* [QuaZip](http://sourceforge.net/projects/quazip/files/quazip/) ~> 0.7.1 ####CMake External Project Dependencies diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d42be3d95..c0e11a72be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -201,6 +201,7 @@ set_property(DIRECTORY PROPERTY EP_PREFIX ${EXTERNAL_PROJECT_PREFIX}) setup_externals_binary_dir() option(USE_NSIGHT "Attempt to find the nSight libraries" 1) +option(GET_QUAZIP "Get QuaZip library automatically as external project" 1) if (WIN32) diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 48fda99b9d..79fa7a1504 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -1,3 +1,9 @@ set(TARGET_NAME script-engine) setup_hifi_library(Gui Network Script ScriptTools WebSockets Widgets) + +add_dependency_external_projects(quazip) +find_package(QuaZip REQUIRED) +target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${QUAZIP_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${QUAZIP_LIBRARIES}) + link_hifi_libraries(shared networking octree gpu ui procedural model model-networking recording avatars fbx entities controllers animation audio physics) diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 3ecb1bfd22..6e9652e134 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -3,7 +3,7 @@ // interface/src/scripting // // Created by Elisa Lupin-Jimenez on 6/28/16. -// Copyright 2014 High Fidelity, Inc. +// Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include "ResourceManager.h" #include "FileScriptingInterface.h" @@ -29,23 +33,78 @@ void FileScriptingInterface::downloadZip() { } // clement's help :D -bool FileScriptingInterface::unzipFile() { +void FileScriptingInterface::unzipFile() { ResourceRequest* request = qobject_cast(sender()); + QUrl url = request->getUrl(); - // Get the file URL - QUrl url = request->getUrl(); + if (request->getResult() == ResourceRequest::Success) { + qDebug() << "Zip file was downloaded"; + QTemporaryDir dir; + QByteArray compressedFileContent = request->getData(); // <-- Downloaded file is in here + QBuffer buffer(&compressedFileContent); + buffer.open(QIODevice::ReadOnly); - if (request->getResult() == ResourceRequest::Success) { - qDebug() << "Success =)"; + QString dirName = dir.path(); + JICompress::extractDir(buffer, dirName); - QByteArray fileContent = request->getData(); // <-- Downloaded file is in here - // Do stuff - // - // unzipFile(fileContent); - - } else { - qDebug() << "Could not download the file =("; + QFileInfoList files = dir.entryInfoList(); + foreach (QFileInfo file, files) { + recursiveFileScan(file); } + + /*foreach (QFileInfo file, files) { + if (file.isDir()) { + if (file.fileName().contains(".zip")) { + qDebug() << "Zip file expanded: " + file.fileName(); + } + + qDebug() << "Regular file logged: " + file.fileName(); + } + }*/ + + + //QString zipFileName = QFile::decodeName(&compressedFileContent); + + //QFile file = + //need to convert this byte array to a file + /*QuaZip zip(zipFileName); + + if (zip.open(QuaZip::mdUnzip)) { + qDebug() << "Opened"; + + for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) { + // do something + qDebug() << zip.getCurrentFileName(); + } + if (zip.getZipError() == UNZ_OK) { + // ok, there was no error + }*/ + + + buffer.close(); + } else { + qDebug() << "Could not download the zip file"; + } + } +void FileScriptingInterface::recursiveFileScan(QFileInfo file) { + if (!file.isDir()) { + qDebug() << "Regular file logged:" + file.fileName(); + return; + } + if (file.fileName().contains(".zip")) { + + } + + QFileInfoList files = file.entryInfoList(); + if (files.empty()) { + files = JlCompress::getFileList(file.fileName()); + } + foreach (QFileInfo file, files) { + if (file.fileName().contains(".zip")) { + + } + } +} diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 67ea207aba..89e3434382 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -3,7 +3,7 @@ // interface/src/scripting // // Created by Elisa Lupin-Jimenez on 6/28/16. -// Copyright 2014 High Fidelity, Inc. +// Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -21,10 +21,17 @@ public: FileScriptingInterface(QObject* parent); public slots: - QScriptValue hasFocus(); + void unzipFile(); + +signals: + void downloadZip(); }; +private: + void downloadZip(); + void unzipFile(); + #endif // hifi_FileScriptingInterface_h \ No newline at end of file From c9c965b1e80a6081d043d64093785fb857a8e743 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Wed, 29 Jun 2016 18:12:52 -0700 Subject: [PATCH 028/134] added new files for quazip --- cmake/externals/quazip/CMakeLists.txt | 37 +++++++++++++++++++++++++++ cmake/modules/FindQuaZip.cmake | 33 ++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 cmake/externals/quazip/CMakeLists.txt create mode 100644 cmake/modules/FindQuaZip.cmake diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt new file mode 100644 index 0000000000..5795e6bc5d --- /dev/null +++ b/cmake/externals/quazip/CMakeLists.txt @@ -0,0 +1,37 @@ +set(EXTERNAL_NAME quazip) + +if (ANDROID) + set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") +endif () + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://headache.hungry.com/~seth/hifi/quazip-0.7.1.tar.gz + URL_MD5 e4a14ad41b9a1ce494f8dd9add56429e + # BUILD_COMMAND ${MAKE_COMMAND} tbb_os=macos + # CONFIGURE_COMMAND "" + # INSTALL_COMMAND ${PLATFORM_BUILD_COMMAND} + CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 +) + +# Hide this external target (for ide users) +set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") + +ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +if (WIN32) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/Debug/QUAZIP_LIB.lib CACHE FILEPATH "Path to QuaZip debug library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/Release/QUAZIP_LIB.lib CACHE FILEPATH "Path to QuaZip release library") +else () + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to QuaZip debug library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip.so CACHE FILEPATH "Path to QuaZip release library") +endif () + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to QuaZip include directory") \ No newline at end of file diff --git a/cmake/modules/FindQuaZip.cmake b/cmake/modules/FindQuaZip.cmake new file mode 100644 index 0000000000..a9f53ec788 --- /dev/null +++ b/cmake/modules/FindQuaZip.cmake @@ -0,0 +1,33 @@ +# +# FindQuaZip.cmake +# +# Once done this will define +# +# QUAZIP_FOUND - system found QuaZip +# QUAZIP_INCLUDE_DIRS - the QuaZip include directory +# QUAZIP_LIBRARIES - link to this to use QuaZip +# +# Created on 2015-8-1 by Seth Alves +# Copyright 2015 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("quazip") + +find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES include HINTS ${QUAZIP_SEARCH_DIRS}) + +find_library(QUAZIP_LIBRARY_DEBUG NAMES QUAZIP QUAZIP_LIB PATH_SUFFIXES lib/Debug HINTS ${QUAZIP_SEARCH_DIRS}) +find_library(QUAZIP_LIBRARY_RELEASE NAMES QUAZIP QUAZIP_LIB PATH_SUFFIXES lib/Release lib HINTS ${QUAZIP_SEARCH_DIRS}) + +include(SelectLibraryConfigurations) +select_library_configurations(QUAZIP) + +set(QUAZIP_LIBRARIES ${QUAZIP_LIBRARY}) + +find_package_handle_standard_args(QUAZIP "Could NOT find QuaZip, try to set the path to QuaZip root folder in the system variable QUAZIP_ROOT_DIR or create a directory quazip in HIFI_LIB_DIR and paste the necessary files there" + QUAZIP_INCLUDE_DIRS QUAZIP_LIBRARIES) + +mark_as_advanced(QUAZIP_INCLUDE_DIRS QUAZIP_LIBRARIES QUAZIP_SEARCH_DIRS) \ No newline at end of file From 87cbb79d673433d949b1f49abdadda0fd1882022 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Tue, 5 Jul 2016 10:34:14 -0700 Subject: [PATCH 029/134] fixing up quazip --- cmake/macros/TargetQuazip.cmake | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 cmake/macros/TargetQuazip.cmake diff --git a/cmake/macros/TargetQuazip.cmake b/cmake/macros/TargetQuazip.cmake new file mode 100644 index 0000000000..f704f03050 --- /dev/null +++ b/cmake/macros/TargetQuazip.cmake @@ -0,0 +1,16 @@ +# +# Copyright 2015 High Fidelity, Inc. +# Created by Leonardo Murillo on 2015/11/20 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# +macro(TARGET_QUAZIP) + add_dependency_external_projects(quazip) + find_package(QuaZip REQUIRED) + target_include_directories(${TARGET_NAME} PUBLIC ${QUAZIP_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${QUAZIP_LIBRARIES}) + if (WIN32) + add_paths_to_fixup_libs(${QUAZIP_DLL_PATH}) + endif () +endmacro() \ No newline at end of file From 212e4f9ccaddf80d8bc9f8a09dc48bd4270c0578 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Tue, 5 Jul 2016 10:38:35 -0700 Subject: [PATCH 030/134] making quazip work --- cmake/externals/quazip/CMakeLists.txt | 53 ++++++++++++------- cmake/modules/FindQuaZip.cmake | 46 ++++++++-------- interface/src/Application.cpp | 2 +- interface/src/Application.h | 2 + libraries/script-engine/CMakeLists.txt | 2 + .../src/FileScriptingInterface.cpp | 35 +++++++----- .../src/FileScriptingInterface.h | 12 ++--- 7 files changed, 87 insertions(+), 65 deletions(-) diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index 5795e6bc5d..413a07efec 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -1,37 +1,52 @@ set(EXTERNAL_NAME quazip) - -if (ANDROID) - set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") -endif () +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) +cmake_policy(SET CMP0046 OLD) include(ExternalProject) + +if (WIN32) + # windows shell does not like backslashes expanded on the command line, + # so convert all backslashes in the QT path to forward slashes + string(REPLACE \\ / QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) +elseif ($ENV{QT_CMAKE_PREFIX_PATH}) + set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) +endif () + ExternalProject_Add( ${EXTERNAL_NAME} - URL http://headache.hungry.com/~seth/hifi/quazip-0.7.1.tar.gz - URL_MD5 e4a14ad41b9a1ce494f8dd9add56429e - # BUILD_COMMAND ${MAKE_COMMAND} tbb_os=macos - # CONFIGURE_COMMAND "" - # INSTALL_COMMAND ${PLATFORM_BUILD_COMMAND} - CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= + URL http://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.6.2.zip + URL_MD5 514851970f1a14d815bdc3ad6267af4d BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=/lib -DZLIB_ROOT=${ZLIB_ROOT} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 ) +add_dependencies(quazip zlib) + # Hide this external target (for ide users) -set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") +set_target_properties(${EXTERNAL_NAME} PROPERTIES + FOLDER "hidden/externals" + INSTALL_NAME_DIR ${INSTALL_DIR}/lib + BUILD_WITH_INSTALL_RPATH True) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include CACHE PATH "List of QuaZip include directories") +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${${EXTERNAL_NAME_UPPER}_INCLUDE_DIR} CACHE PATH "List of QuaZip include directories") +set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/lib CACHE FILEPATH "Location of QuaZip DLL") -string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) - -if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/Debug/QUAZIP_LIB.lib CACHE FILEPATH "Path to QuaZip debug library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/Release/QUAZIP_LIB.lib CACHE FILEPATH "Path to QuaZip release library") +if (APPLE) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library") +elseif (WIN32) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip.lib CACHE FILEPATH "Location of QuaZip release library") else () - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to QuaZip debug library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip.so CACHE FILEPATH "Path to QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip.so CACHE FILEPATH "Location of QuaZip release library") endif () -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to QuaZip include directory") \ No newline at end of file +include(SelectLibraryConfigurations) +select_library_configurations(${EXTERNAL_NAME_UPPER}) + +# Force selected libraries into the cache +set(${EXTERNAL_NAME_UPPER}_LIBRARY ${${EXTERNAL_NAME_UPPER}_LIBRARY} CACHE FILEPATH "Location of QuaZip libraries") +set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries") \ No newline at end of file diff --git a/cmake/modules/FindQuaZip.cmake b/cmake/modules/FindQuaZip.cmake index a9f53ec788..2b2a577919 100644 --- a/cmake/modules/FindQuaZip.cmake +++ b/cmake/modules/FindQuaZip.cmake @@ -1,33 +1,29 @@ # -# FindQuaZip.cmake -# -# Once done this will define -# -# QUAZIP_FOUND - system found QuaZip -# QUAZIP_INCLUDE_DIRS - the QuaZip include directory -# QUAZIP_LIBRARIES - link to this to use QuaZip -# -# Created on 2015-8-1 by Seth Alves -# Copyright 2015 High Fidelity, Inc. -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# FindQuaZip.h +# StackManagerQt/cmake/modules # +# Created by Mohammed Nafees. +# Copyright (c) 2014 High Fidelity. All rights reserved. +# + +# QUAZIP_FOUND - QuaZip library was found +# QUAZIP_INCLUDE_DIR - Path to QuaZip include dir +# QUAZIP_INCLUDE_DIRS - Path to QuaZip and zlib include dir (combined from QUAZIP_INCLUDE_DIR + ZLIB_INCLUDE_DIR) +# QUAZIP_LIBRARIES - List of QuaZip libraries +# QUAZIP_ZLIB_INCLUDE_DIR - The include dir of zlib headers include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") hifi_library_search_hints("quazip") -find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES include HINTS ${QUAZIP_SEARCH_DIRS}) +if (WIN32) + find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES include/quazip HINTS ${QUAZIP_SEARCH_DIRS}) +elseif (APPLE) + find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES include/quazip HINTS ${QUAZIP_SEARCH_DIRS}) +else () + find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES quazip HINTS ${QUAZIP_SEARCH_DIRS}) +endif () -find_library(QUAZIP_LIBRARY_DEBUG NAMES QUAZIP QUAZIP_LIB PATH_SUFFIXES lib/Debug HINTS ${QUAZIP_SEARCH_DIRS}) -find_library(QUAZIP_LIBRARY_RELEASE NAMES QUAZIP QUAZIP_LIB PATH_SUFFIXES lib/Release lib HINTS ${QUAZIP_SEARCH_DIRS}) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(QUAZIP DEFAULT_MSG QUAZIP_INCLUDE_DIRS) -include(SelectLibraryConfigurations) -select_library_configurations(QUAZIP) - -set(QUAZIP_LIBRARIES ${QUAZIP_LIBRARY}) - -find_package_handle_standard_args(QUAZIP "Could NOT find QuaZip, try to set the path to QuaZip root folder in the system variable QUAZIP_ROOT_DIR or create a directory quazip in HIFI_LIB_DIR and paste the necessary files there" - QUAZIP_INCLUDE_DIRS QUAZIP_LIBRARIES) - -mark_as_advanced(QUAZIP_INCLUDE_DIRS QUAZIP_LIBRARIES QUAZIP_SEARCH_DIRS) \ No newline at end of file +mark_as_advanced(QUAZIP_INCLUDE_DIRS QUAZIP_SEARCH_DIRS) \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 08788cb5bc..4be9a3c5c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2016,7 +2016,7 @@ bool Application::importSVOFromURL(const QString& urlString) { } // attempt to start ZIP download project -bool Appplication::importZIPFromURL(const QString& urlString) { +bool Application::importZIPFromURL(const QString& urlString) { emit zipImportRequested(urlString); return true; } diff --git a/interface/src/Application.h b/interface/src/Application.h index 0af65f665f..d8f02f41b7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -250,6 +250,7 @@ public: signals: void svoImportRequested(const QString& url); + void zipImportRequested(const QString& url); void fullAvatarURLChanged(const QString& newValue, const QString& modelName); @@ -385,6 +386,7 @@ private: bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); + bool importZIPFromURL(const QString& urlString); bool nearbyEntitiesAreReadyForPhysics(); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 79fa7a1504..b484937ea5 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -1,6 +1,8 @@ set(TARGET_NAME script-engine) setup_hifi_library(Gui Network Script ScriptTools WebSockets Widgets) +target_zlib() + add_dependency_external_projects(quazip) find_package(QuaZip REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${QUAZIP_INCLUDE_DIRS}) diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 6e9652e134..017c3f83e1 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -11,17 +11,20 @@ #include #include +#include +#include #include #include #include +#include #include -#include +#include #include "ResourceManager.h" #include "FileScriptingInterface.h" -FileScriptingInterface::FileScriptingInterface(QObject* parent) { +FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent) { // nothing for now } @@ -45,11 +48,11 @@ void FileScriptingInterface::unzipFile() { buffer.open(QIODevice::ReadOnly); QString dirName = dir.path(); - JICompress::extractDir(buffer, dirName); + JlCompress::extractDir(buffer, dirName); QFileInfoList files = dir.entryInfoList(); foreach (QFileInfo file, files) { - recursiveFileScan(file); + recursiveFileScan(file, &dirName); } @@ -89,22 +92,26 @@ void FileScriptingInterface::unzipFile() { } -void FileScriptingInterface::recursiveFileScan(QFileInfo file) { +void FileScriptingInterface::recursiveFileScan(QFileInfo file, QString* dirName) { if (!file.isDir()) { - qDebug() << "Regular file logged:" + file.fileName(); + qDebug() << "Regular file logged: " + file.fileName(); return; } + QFileInfoList files; + if (file.fileName().contains(".zip")) { - - } + JlCompress::extractDir(file); + qDebug() << "Extracting archive: " + file.fileName(); + } + files = file.entryInfoList(); - QFileInfoList files = file.entryInfoList(); - if (files.empty()) { + /*if (files.empty()) { files = JlCompress::getFileList(file.fileName()); - } - foreach (QFileInfo file, files) { - if (file.fileName().contains(".zip")) { + }*/ - } + foreach (QFileInfo file, files) { + qDebug() << "Looking into file: " + file.fileName(); + recursiveFileScan(file, &dirName); } + return; } diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 89e3434382..cf965afa34 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -13,6 +13,7 @@ #define hifi_FileScriptingInterface_h #include +#include class FileScriptingInterface : public QObject { Q_OBJECT @@ -26,12 +27,11 @@ public slots: signals: void downloadZip(); +private: + //void downloadZip(); + //void unzipFile(); + void recursiveFileScan(QFileInfo file, QString* dirName); + }; -private: - void downloadZip(); - void unzipFile(); - - - #endif // hifi_FileScriptingInterface_h \ No newline at end of file From 9833ba19878bcc2b5e493ba00b69b587eecc2c88 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Wed, 6 Jul 2016 16:43:23 -0700 Subject: [PATCH 031/134] No errors upon build --- cmake/externals/quazip/CMakeLists.txt | 10 ++--- libraries/script-engine/CMakeLists.txt | 4 ++ .../src/FileScriptingInterface.cpp | 45 +++++++++++++------ .../src/FileScriptingInterface.h | 9 ++-- scripts/system/edit.js | 7 ++- 5 files changed, 52 insertions(+), 23 deletions(-) diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index 413a07efec..bf51a52fc5 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -14,8 +14,8 @@ endif () ExternalProject_Add( ${EXTERNAL_NAME} - URL http://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.6.2.zip - URL_MD5 514851970f1a14d815bdc3ad6267af4d + URL https://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.7.2.zip + URL_MD5 2955176048a31262c09259ca8d309d19 BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=/lib -DZLIB_ROOT=${ZLIB_ROOT} LOG_DOWNLOAD 1 @@ -37,11 +37,11 @@ set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${${EXTERNAL_NAME_UPPER}_INCLUDE_DIR} CA set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/lib CACHE FILEPATH "Location of QuaZip DLL") if (APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5d.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library") elseif (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip.lib CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library") else () - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip.so CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library") endif () include(SelectLibraryConfigurations) diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index b484937ea5..c3a9a9f38a 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -8,4 +8,8 @@ find_package(QuaZip REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${QUAZIP_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${QUAZIP_LIBRARIES}) +if (WIN32) + add_paths_to_fixup_libs(${QUAZIP_DLL_PATH}) +endif () + link_hifi_libraries(shared networking octree gpu ui procedural model model-networking recording avatars fbx entities controllers animation audio physics) diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 017c3f83e1..814a054e5e 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -1,6 +1,6 @@ // // FileScriptingInterface.cpp -// interface/src/scripting +// libraries/script-engine/src // // Created by Elisa Lupin-Jimenez on 6/28/16. // Copyright 2016 High Fidelity, Inc. @@ -10,15 +10,18 @@ // #include +#include #include #include #include +#include +#include #include #include #include #include -#include -#include +#include +#include #include "ResourceManager.h" #include "FileScriptingInterface.h" @@ -28,27 +31,43 @@ FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent // nothing for now } -void FileScriptingInterface::downloadZip() { - QUrl url(*parent); +void FileScriptingInterface::runUnzip(QString path, QString importURL) { + downloadZip(path, importURL); + +} + +QString FileScriptingInterface::getTempDir() { + QTemporaryDir dir; + dir.setAutoRemove(false); + return dir.path(); + // remember I must do something to delete this temp dir later +} + +void FileScriptingInterface::downloadZip(QString path, const QString link) { + QUrl url = QUrl(link); auto request = ResourceManager::createResourceRequest(nullptr, url); - connect(request, &ResourceRequest::finished, this, &FileScriptingInterface::unzipFile); + connect(request, &ResourceRequest::finished, this, [this, path]{ + unzipFile(path); + }); request->send(); } // clement's help :D -void FileScriptingInterface::unzipFile() { +void FileScriptingInterface::unzipFile(QString path) { ResourceRequest* request = qobject_cast(sender()); QUrl url = request->getUrl(); if (request->getResult() == ResourceRequest::Success) { qDebug() << "Zip file was downloaded"; - QTemporaryDir dir; + QDir dir(path); QByteArray compressedFileContent = request->getData(); // <-- Downloaded file is in here QBuffer buffer(&compressedFileContent); buffer.open(QIODevice::ReadOnly); + //QString zipFileName = QFile::decodeName(compressedFileContent); QString dirName = dir.path(); - JlCompress::extractDir(buffer, dirName); + qDebug() << "Zip directory is stored at: " + dirName; + JlCompress::extractDir(&buffer, dirName); QFileInfoList files = dir.entryInfoList(); foreach (QFileInfo file, files) { @@ -67,7 +86,7 @@ void FileScriptingInterface::unzipFile() { }*/ - //QString zipFileName = QFile::decodeName(&compressedFileContent); + //QFile file = //need to convert this byte array to a file @@ -100,10 +119,10 @@ void FileScriptingInterface::recursiveFileScan(QFileInfo file, QString* dirName) QFileInfoList files; if (file.fileName().contains(".zip")) { - JlCompress::extractDir(file); + JlCompress::extractDir(file.fileName()); qDebug() << "Extracting archive: " + file.fileName(); } - files = file.entryInfoList(); + files = file.dir().entryInfoList(); /*if (files.empty()) { files = JlCompress::getFileList(file.fileName()); @@ -111,7 +130,7 @@ void FileScriptingInterface::recursiveFileScan(QFileInfo file, QString* dirName) foreach (QFileInfo file, files) { qDebug() << "Looking into file: " + file.fileName(); - recursiveFileScan(file, &dirName); + recursiveFileScan(file, dirName); } return; } diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index cf965afa34..a9ccd3442f 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -1,6 +1,6 @@ // // FileScriptingInterface.h -// interface/src/scripting +// libraries/script-engine/src // // Created by Elisa Lupin-Jimenez on 6/28/16. // Copyright 2016 High Fidelity, Inc. @@ -14,23 +14,26 @@ #include #include +#include class FileScriptingInterface : public QObject { Q_OBJECT public: FileScriptingInterface(QObject* parent); + void runUnzip(QString path, QString importURL); + QString getTempDir(); public slots: - void unzipFile(); + void unzipFile(QString path); signals: - void downloadZip(); private: //void downloadZip(); //void unzipFile(); void recursiveFileScan(QFileInfo file, QString* dirName); + void downloadZip(QString path, const QString link); }; diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 18a76eb45f..f096deb0a7 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1208,10 +1208,13 @@ Window.svoImportRequested.connect(importSVO); // attempt to start ZIP download project function importZIP(importURL) { print("Import ZIP requested: " + importURL); - if (!Entities.canAdjustLocks()) { + /*if (!Entities.canAdjustLocks()) { Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); return; - } + }*/ + var path = File.getTempDir(); + print("Temporary path to zip: " + path); + File.runUnzip(path, importURL); } From 76a847d34f1ca3df84d7606f796f5c02e97742f3 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Fri, 8 Jul 2016 10:54:11 -0700 Subject: [PATCH 032/134] testing for URL bug --- interface/src/Application.cpp | 7 +++++-- interface/src/scripting/WindowScriptingInterface.cpp | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4be9a3c5c1..3d0a4628b1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2010,13 +2010,13 @@ bool Application::importJSONFromURL(const QString& urlString) { } bool Application::importSVOFromURL(const QString& urlString) { - emit svoImportRequested(urlString); return true; } // attempt to start ZIP download project bool Application::importZIPFromURL(const QString& urlString) { + qDebug() << "zip import request has been emitted"; emit zipImportRequested(urlString); return true; } @@ -2141,13 +2141,16 @@ bool Application::event(QEvent* event) { // handle custom URL if (event->type() == QEvent::FileOpen) { - QFileOpenEvent* fileEvent = static_cast(event); + qDebug() << "we have received one url!: "; + QFileOpenEvent* fileEvent = static_cast(event); QUrl url = fileEvent->url(); if (!url.isEmpty()) { QString urlString = url.toString(); + qDebug() << "we got a url!: " + urlString; if (canAcceptURL(urlString)) { + qDebug() << "we got an ACCEPTED url!: " + urlString; return acceptURL(urlString); } } diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 4a4f4b1025..2ea562143e 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -61,6 +61,7 @@ WindowScriptingInterface::WindowScriptingInterface() { }); // attempt to start ZIP download project connect(qApp, &Application::zipImportRequested, [this](const QString& urlString) { + qDebug() << "zip import has been requested"; static const QMetaMethod zipImportRequestedSignal = QMetaMethod::fromSignal(&WindowScriptingInterface::zipImportRequested); From eab7714d70ccda26395a8b05c444dc42fc68db68 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Wed, 13 Jul 2016 12:47:19 -0700 Subject: [PATCH 033/134] working within webview to access url --- interface/resources/qml/Browser.qml | 1 + .../resources/qml/controls-uit/WebView.qml | 16 +++- interface/src/Application.cpp | 18 ++++- libraries/ui/src/OffscreenUi.cpp | 3 + scripts/system/examples.js | 77 +++++++++++++++++++ 5 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 scripts/system/examples.js diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 47231957c2..33595c2038 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -223,6 +223,7 @@ ScrollingWindow { var newWindow = component.createObject(desktop); request.openIn(newWindow.webView) } + //profile: desktop.browserProfile } diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index b599e29fe0..99064cdcbd 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -49,6 +49,7 @@ WebEngineView { onLoadingChanged: { // Required to support clicking on "hifi://" links + console.log("loading change requested url"); if (WebEngineView.LoadStartedStatus == loadRequest.status) { var url = loadRequest.url.toString(); if (urlHandler.canHandleUrl(url)) { @@ -59,12 +60,19 @@ WebEngineView { } } - onNewViewRequested:{ - var component = Qt.createComponent("../Browser.qml"); - var newWindow = component.createObject(desktop); - request.openIn(newWindow.webView) + onNewViewRequested: { + console.log("new view requested url"); + console.log(request.url.toString()); + //if (toString(request.url) ) + var component = Qt.createComponent("../Browser.qml"); + var newWindow = component.createObject(desktop); + request.openIn(newWindow.webView); } + onLinkHovered: { + console.log(hoveredUrl); + } + // This breaks the webchannel used for passing messages. Fixed in Qt 5.6 // See https://bugreports.qt.io/browse/QTBUG-49521 //profile: desktop.browserProfile diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3d0a4628b1..2fee3488f9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -354,6 +354,7 @@ public: if (message->message == WM_COPYDATA) { COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)(message->lParam); + qDebug() << "os windows url for some reason"; QUrl url = QUrl((const char*)(pcds->lpData)); if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) { DependencyManager::get()->handleLookupString(url.toString()); @@ -2157,6 +2158,10 @@ bool Application::event(QEvent* event) { return false; } + if (event->type() == QEvent::None) { + qDebug() << "this url just didn't click"; + } + if (HFActionEvent::types().contains(event->type())) { _controllerScriptingInterface->handleMetaEvent(static_cast(event)); } @@ -3180,6 +3185,7 @@ void Application::saveSettings() const { } bool Application::importEntities(const QString& urlOrFilename) { + qDebug() << "import entities url"; bool success = false; _entityClipboard->withWriteLock([&] { _entityClipboard->eraseAllOctreeElements(); @@ -4789,6 +4795,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri } bool Application::canAcceptURL(const QString& urlString) const { + qDebug() << "stepping through 'canAcceptURL'"; QUrl url(urlString); if (urlString.startsWith(HIFI_URL_SCHEME)) { return true; @@ -4805,6 +4812,7 @@ bool Application::canAcceptURL(const QString& urlString) const { } bool Application::acceptURL(const QString& urlString, bool defaultUpload) { + qDebug() << "stepping through 'acceptURL'"; if (urlString.startsWith(HIFI_URL_SCHEME)) { // this is a hifi URL - have the AddressManager handle it QMetaObject::invokeMethod(DependencyManager::get().data(), "handleLookupString", @@ -4834,6 +4842,7 @@ void Application::setSessionUUID(const QUuid& sessionUUID) const { } bool Application::askToSetAvatarUrl(const QString& url) { + qDebug() << "setting avatar url"; QUrl realUrl(url); if (realUrl.isLocalFile()) { OffscreenUi::warning("", "You can not use local files for avatar components."); @@ -4890,6 +4899,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { bool Application::askToLoadScript(const QString& scriptFilenameOrURL) { + qDebug() << "setting script url"; QMessageBox::StandardButton reply; QString shortName = scriptFilenameOrURL; @@ -4914,7 +4924,7 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) { } bool Application::askToWearAvatarAttachmentUrl(const QString& url) { - + qDebug() << "setting avatar attachment url"; QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest = QNetworkRequest(url); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); @@ -4996,6 +5006,7 @@ bool Application::displayAvatarAttachmentConfirmationDialog(const QString& name) } void Application::toggleRunningScriptsWidget() const { + qDebug() << "toggle running scripts url"; static const QUrl url("hifi/dialogs/RunningScripts.qml"); DependencyManager::get()->show(url, "RunningScripts"); //if (_runningScriptsWidget->isVisible()) { @@ -5013,10 +5024,11 @@ void Application::toggleRunningScriptsWidget() const { } void Application::toggleAssetServerWidget(QString filePath) { + qDebug() << "toggle asset before if"; if (!DependencyManager::get()->getThisNodeCanWriteAssets()) { return; } - + qDebug() << "toggle asset after if"; static const QUrl url { "AssetServer.qml" }; auto startUpload = [=](QQmlContext* context, QObject* newObject){ @@ -5033,6 +5045,7 @@ void Application::packageModel() { } void Application::openUrl(const QUrl& url) const { + qDebug() << "open url"; if (!url.isEmpty()) { if (url.scheme() == HIFI_URL_SCHEME) { DependencyManager::get()->handleLookupString(url.toString()); @@ -5063,6 +5076,7 @@ void Application::setPreviousScriptLocation(const QString& location) { } void Application::loadScriptURLDialog() const { + qDebug() << "load script url dialog"; auto newScript = OffscreenUi::getText(nullptr, "Open and Run Script", "Script URL"); if (!newScript.isEmpty()) { DependencyManager::get()->loadScript(newScript); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 06ef456006..82a9186f92 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -78,17 +78,20 @@ class UrlHandler : public QObject { Q_OBJECT public: Q_INVOKABLE bool canHandleUrl(const QString& url) { + qDebug() << Q_FUNC_INFO; static auto handler = dynamic_cast(qApp); return handler->canAcceptURL(url); } Q_INVOKABLE bool handleUrl(const QString& url) { + qDebug() << Q_FUNC_INFO; static auto handler = dynamic_cast(qApp); return handler->acceptURL(url); } // FIXME hack for authentication, remove when we migrate to Qt 5.6 Q_INVOKABLE QString fixupUrl(const QString& originalUrl) { + qDebug() << Q_FUNC_INFO; return fixupHifiUrl(originalUrl); } }; diff --git a/scripts/system/examples.js b/scripts/system/examples.js new file mode 100644 index 0000000000..32d977834b --- /dev/null +++ b/scripts/system/examples.js @@ -0,0 +1,77 @@ +// +// examples.js +// examples +// +// Created by Eric Levin on 8 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var toolIconUrl = Script.resolvePath("assets/images/tools/"); + +var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples"; +//var EXAMPLES_URL = "https://clara.io/view/c1c4d926-5648-4fd3-9673-6d9018ad4627"; +//var EXAMPLES_URL = "http://s3.amazonaws.com/DreamingContent/test.html"; + +var examplesWindow = new OverlayWebWindow({ + title: 'Examples', + source: "about:blank", + width: 900, + height: 700, + visible: false +}); + +var toolHeight = 50; +var toolWidth = 50; +var TOOLBAR_MARGIN_Y = 0; + + +function showExamples(marketplaceID) { + var url = EXAMPLES_URL; + if (marketplaceID) { + url = url + "/items/" + marketplaceID; + } + print("setting examples URL to " + url); + examplesWindow.setURL(url); + examplesWindow.setVisible(true); + + UserActivityLogger.openedMarketplace(); +} + +function hideExamples() { + examplesWindow.setVisible(false); + examplesWindow.setURL("about:blank"); +} + +function toggleExamples() { + if (examplesWindow.visible) { + hideExamples(); + } else { + showExamples(); + } +} + +var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + +var browseExamplesButton = toolBar.addButton({ + imageURL: toolIconUrl + "market.svg", + objectName: "examples", + buttonState: 1, + alpha: 0.9 +}); + +function onExamplesWindowVisibilityChanged() { + browseExamplesButton.writeProperty('buttonState', examplesWindow.visible ? 0 : 1); +} +function onClick() { + toggleExamples(); +} +browseExamplesButton.clicked.connect(onClick); +examplesWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); + +Script.scriptEnding.connect(function () { + browseExamplesButton.clicked.disconnect(onClick); + examplesWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); +}); From 6152fa28b7bc908a554609a01c14f7e6e72720e0 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Mon, 18 Jul 2016 15:29:15 -0700 Subject: [PATCH 034/134] Download through QML It kind of works, not crashing like before, but the weird ghost file/type error is still happening with multiple downloads --- interface/resources/qml/Browser.qml | 25 +++++++++++++++---- .../resources/qml/controls-uit/WebView.qml | 3 +-- interface/src/Application.cpp | 2 ++ .../src/FileScriptingInterface.cpp | 6 ++--- .../src/FileScriptingInterface.h | 7 +++--- scripts/system/edit.js | 2 +- scripts/system/examples.js | 6 +++-- 7 files changed, 35 insertions(+), 16 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 33595c2038..7436328dd8 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -218,12 +218,27 @@ ScrollingWindow { onIconChanged: { console.log("New icon: " + icon) } - onNewViewRequested:{ - var component = Qt.createComponent("Browser.qml"); - var newWindow = component.createObject(desktop); - request.openIn(newWindow.webView) - } + Component.onCompleted: { + webview.profile.downloadRequested.connect(function(download){ + console.log("Download start: " + download.state) + download.accept() + console.log("Download accept: " + download.state) + if (download.state === WebEngineDownloadItem.DownloadInterrupted) { + console.log("Download? " + download.state) + console.log("download failed to complete") + } + }) + + webview.profile.downloadFinished.connect(function(download){ + console.log("Download Finished: " + download.state) + if (download.state === WebEngineDownloadItem.DownloadCompleted) {console.log("getting download completed state")} + console.log("download success") + File.runUnzip(download.path) + }) + } + + //profile: desktop.browserProfile } diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index 99064cdcbd..3d3fc20888 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -62,8 +62,7 @@ WebEngineView { onNewViewRequested: { console.log("new view requested url"); - console.log(request.url.toString()); - //if (toString(request.url) ) + //console.log("new view requested url" + request.url.toString()); var component = Qt.createComponent("../Browser.qml"); var newWindow = component.createObject(desktop); request.openIn(newWindow.webView); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2fee3488f9..ccffceede0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -1542,6 +1543,7 @@ void Application::initializeUi() { rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance()); rootContext->setContextProperty("Controller", DependencyManager::get().data()); rootContext->setContextProperty("Entities", DependencyManager::get().data()); + rootContext->setContextProperty("File", new FileScriptingInterface(engine)); rootContext->setContextProperty("MyAvatar", getMyAvatar()); rootContext->setContextProperty("Messages", DependencyManager::get().data()); rootContext->setContextProperty("Recording", DependencyManager::get().data()); diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 814a054e5e..ea6f42a44a 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -31,9 +31,9 @@ FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent // nothing for now } -void FileScriptingInterface::runUnzip(QString path, QString importURL) { - downloadZip(path, importURL); - +void FileScriptingInterface::runUnzip(QString path) { + //downloadZip(path, importURL); + qDebug() << "Path where download is saved: " + path; } QString FileScriptingInterface::getTempDir() { diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index a9ccd3442f..0e12d3aa47 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -21,17 +21,18 @@ class FileScriptingInterface : public QObject { public: FileScriptingInterface(QObject* parent); - void runUnzip(QString path, QString importURL); + //void runUnzip(QString path, QString importURL); QString getTempDir(); public slots: - void unzipFile(QString path); + //void unzipFile(QString path); + void runUnzip(QString path); signals: private: //void downloadZip(); - //void unzipFile(); + void unzipFile(QString path); void recursiveFileScan(QFileInfo file, QString* dirName); void downloadZip(QString path, const QString link); diff --git a/scripts/system/edit.js b/scripts/system/edit.js index f096deb0a7..1284202c6d 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1205,7 +1205,7 @@ function importSVO(importURL) { } Window.svoImportRequested.connect(importSVO); -// attempt to start ZIP download project +// attempt to start ZIP download project, GET RID OF THIS function importZIP(importURL) { print("Import ZIP requested: " + importURL); /*if (!Entities.canAdjustLocks()) { diff --git a/scripts/system/examples.js b/scripts/system/examples.js index 32d977834b..f67dd407bb 100644 --- a/scripts/system/examples.js +++ b/scripts/system/examples.js @@ -11,9 +11,11 @@ var toolIconUrl = Script.resolvePath("assets/images/tools/"); -var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples"; +//var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples"; //var EXAMPLES_URL = "https://clara.io/view/c1c4d926-5648-4fd3-9673-6d9018ad4627"; -//var EXAMPLES_URL = "http://s3.amazonaws.com/DreamingContent/test.html"; +var EXAMPLES_URL = "http://s3.amazonaws.com/DreamingContent/test.html"; +//var EXAMPLES_URL = "https://hifi-content.s3.amazonaws.com/elisalj/test.html"; +//var EXAMPLES_URL = "https://hifi-content.s3.amazonaws.com/elisalj/test_download.html"; var examplesWindow = new OverlayWebWindow({ title: 'Examples', From ab02d16eb7656ea0a37785a398716fad62dff045 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Mon, 18 Jul 2016 19:37:24 -0700 Subject: [PATCH 035/134] QML troubleshooting Trying to find out why it does multiple downloads on one click, when everything fails. Has something to do with a download finish request getting sent despite not being completed. --- interface/resources/qml/Browser.qml | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 7436328dd8..e9421d5ad1 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -221,20 +221,25 @@ ScrollingWindow { Component.onCompleted: { webview.profile.downloadRequested.connect(function(download){ - console.log("Download start: " + download.state) - download.accept() - console.log("Download accept: " + download.state) - if (download.state === WebEngineDownloadItem.DownloadInterrupted) { - console.log("Download? " + download.state) - console.log("download failed to complete") + if (download.state === WebEngineDownloadItem.DownloadRequested) { + console.log("Download start: " + download.state) + download.accept() + console.log("Download accept: " + download.state) + if (download.state === WebEngineDownloadItem.DownloadInterrupted) { + console.log("Download? " + download.state) + console.log("download failed to complete") + } } }) webview.profile.downloadFinished.connect(function(download){ - console.log("Download Finished: " + download.state) - if (download.state === WebEngineDownloadItem.DownloadCompleted) {console.log("getting download completed state")} - console.log("download success") - File.runUnzip(download.path) + if (download.state === WebEngineDownloadItem.DownloadCompleted) { + console.log("Download Finished: " + download.state) + console.log("File object is: " + File) + File.runUnzip(download.path) + } else { + console.log("The download was corrupted") + } }) } From c36fc29363c9772a479cf01dd3eea3d2d5257146 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Tue, 19 Jul 2016 19:48:16 -0700 Subject: [PATCH 036/134] Zip download works --- interface/resources/qml/Browser.qml | 29 +++----------- .../resources/qml/controls-uit/WebView.qml | 7 +++- interface/resources/qml/hifi/Desktop.qml | 39 +++++++++++++++++++ .../src/FileScriptingInterface.cpp | 38 ++++++++++++------ .../src/FileScriptingInterface.h | 6 ++- 5 files changed, 82 insertions(+), 37 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index e9421d5ad1..79d045cf0f 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -140,6 +140,7 @@ ScrollingWindow { } } +<<<<<<< ab02d16eb7656ea0a37785a398716fad62dff045 Rectangle { id:permissionsContainer visible:false @@ -196,6 +197,8 @@ ScrollingWindow { } } } +======= +>>>>>>> Zip download works WebEngineView { id: webview @@ -220,35 +223,15 @@ ScrollingWindow { } Component.onCompleted: { - webview.profile.downloadRequested.connect(function(download){ - if (download.state === WebEngineDownloadItem.DownloadRequested) { - console.log("Download start: " + download.state) - download.accept() - console.log("Download accept: " + download.state) - if (download.state === WebEngineDownloadItem.DownloadInterrupted) { - console.log("Download? " + download.state) - console.log("download failed to complete") - } - } - }) - - webview.profile.downloadFinished.connect(function(download){ - if (download.state === WebEngineDownloadItem.DownloadCompleted) { - console.log("Download Finished: " + download.state) - console.log("File object is: " + File) - File.runUnzip(download.path) - } else { - console.log("The download was corrupted") - } - }) + desktop.initWebviewProfileHandlers(webview.profile) } - //profile: desktop.browserProfile } } // item - + + Keys.onPressed: { switch(event.key) { case Qt.Key_L: diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index 3d3fc20888..3ab1478750 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -69,9 +69,14 @@ WebEngineView { } onLinkHovered: { - console.log(hoveredUrl); + desktop.currentUrl = hoveredUrl + console.log("my url in WebView: " + desktop.currentUrl) } + //onLinkHovered: { + // console.log(hoveredUrl); + //} + // This breaks the webchannel used for passing messages. Fixed in Qt 5.6 // See https://bugreports.qt.io/browse/QTBUG-49521 //profile: desktop.browserProfile diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 561bd722f2..29f982887c 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -71,6 +71,45 @@ OriginalDesktop.Desktop { }); } + // Accept a download through the webview + property bool webViewProfileSetup: false + property string currentUrl: "" + property string adaptedPath: "" + function initWebviewProfileHandlers(profile) { + console.log("the webview url in desktop is: " + currentUrl) + if (webViewProfileSetup) return; + webViewProfileSetup = true; + + profile.downloadRequested.connect(function(download){ + console.log("Download start: " + download.state) + if (!File.testUrl(currentUrl)) { + console.log("This file type is not accepted. Look for a zip file") + download.cancel() + return + } + adaptedPath = File.convertUrlToPath(currentUrl) + download.path = "C:/Users/elisa/Downloads/" + adaptedPath + console.log("Path where it should download: " + download.path) + download.accept() + console.log("Download accept: " + download.state) + if (download.state === WebEngineDownloadItem.DownloadInterrupted) { + console.log("Download? " + download.state) + console.log("download failed to complete") + } + }) + + profile.downloadFinished.connect(function(download){ + if (download.state === WebEngineDownloadItem.DownloadCompleted) { + console.log("Download Finished: " + download.state) + console.log("File object is: " + File) + File.runUnzip(download.path, currentUrl) + //download.cancel() + } else { + console.log("The download was corrupted, state: " + download.state) + } + }) + } + // Create or fetch a toolbar with the given name function getToolbar(name) { var result = toolbars[name]; diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index ea6f42a44a..937618e9aa 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -31,9 +31,15 @@ FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent // nothing for now } -void FileScriptingInterface::runUnzip(QString path) { - //downloadZip(path, importURL); +void FileScriptingInterface::runUnzip(QString path, QUrl url) { + qDebug() << "Url that was downloaded: " + url.toString(); qDebug() << "Path where download is saved: " + path; + unzipFile(path); +} + +bool FileScriptingInterface::testUrl(QUrl url) { + if (url.toString().contains(".zip")) return true; + return false; } QString FileScriptingInterface::getTempDir() { @@ -43,6 +49,14 @@ QString FileScriptingInterface::getTempDir() { // remember I must do something to delete this temp dir later } +QString FileScriptingInterface::convertUrlToPath(QUrl url) { + QString newUrl; + QString oldUrl = url.toString(); + newUrl = oldUrl.section("filename=", 1, 1); + qDebug() << "Filename should be: " + newUrl; + return newUrl; +} + void FileScriptingInterface::downloadZip(QString path, const QString link) { QUrl url = QUrl(link); auto request = ResourceManager::createResourceRequest(nullptr, url); @@ -54,15 +68,15 @@ void FileScriptingInterface::downloadZip(QString path, const QString link) { // clement's help :D void FileScriptingInterface::unzipFile(QString path) { - ResourceRequest* request = qobject_cast(sender()); - QUrl url = request->getUrl(); + //ResourceRequest* request = qobject_cast(sender()); + //QUrl url = request->getUrl(); - if (request->getResult() == ResourceRequest::Success) { + //if (request->getResult() == ResourceRequest::Success) { qDebug() << "Zip file was downloaded"; QDir dir(path); - QByteArray compressedFileContent = request->getData(); // <-- Downloaded file is in here - QBuffer buffer(&compressedFileContent); - buffer.open(QIODevice::ReadOnly); + //QByteArray compressedFileContent = request->getData(); // <-- Downloaded file is in here + //QBuffer buffer(&compressedFileContent); + //buffer.open(QIODevice::ReadOnly); //QString zipFileName = QFile::decodeName(compressedFileContent); QString dirName = dir.path(); @@ -104,10 +118,10 @@ void FileScriptingInterface::unzipFile(QString path) { }*/ - buffer.close(); - } else { - qDebug() << "Could not download the zip file"; - } + //buffer.close(); + //} else { + // qDebug() << "Could not download the zip file"; + //} } diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 0e12d3aa47..6ba6044060 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -21,12 +21,16 @@ class FileScriptingInterface : public QObject { public: FileScriptingInterface(QObject* parent); + //void runUnzip(QString path, QString importURL); QString getTempDir(); + public slots: //void unzipFile(QString path); - void runUnzip(QString path); + bool testUrl(QUrl url); + QString convertUrlToPath(QUrl url); + void runUnzip(QString path, QUrl url); signals: From 49712060ed6e9cf9390365b9c551ab0f4792fdf6 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Thu, 21 Jul 2016 17:43:19 -0700 Subject: [PATCH 037/134] switching to the main site progress --- interface/resources/qml/Browser.qml | 1 + .../resources/qml/controls-uit/WebView.qml | 4 ---- .../src/FileScriptingInterface.cpp | 20 ++++++++++++------- scripts/system/examples.js | 4 ++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 79d045cf0f..f3bdab74f4 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -225,6 +225,7 @@ ScrollingWindow { Component.onCompleted: { desktop.initWebviewProfileHandlers(webview.profile) } + //profile: desktop.browserProfile } diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index 3ab1478750..5fa0f5f584 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -73,10 +73,6 @@ WebEngineView { console.log("my url in WebView: " + desktop.currentUrl) } - //onLinkHovered: { - // console.log(hoveredUrl); - //} - // This breaks the webchannel used for passing messages. Fixed in Qt 5.6 // See https://bugreports.qt.io/browse/QTBUG-49521 //profile: desktop.browserProfile diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 937618e9aa..ad4ae8bdc2 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -80,12 +80,18 @@ void FileScriptingInterface::unzipFile(QString path) { //QString zipFileName = QFile::decodeName(compressedFileContent); QString dirName = dir.path(); + QDir testPath("C:/Users/elisa/Downloads/banana.zip"); qDebug() << "Zip directory is stored at: " + dirName; - JlCompress::extractDir(&buffer, dirName); + QStringList list = JlCompress::extractDir(testPath.path(), "C:/Users/elisa/Downloads/test"); - QFileInfoList files = dir.entryInfoList(); - foreach (QFileInfo file, files) { - recursiveFileScan(file, &dirName); + qDebug() << list; + + //QFileInfoList files = dir.entryInfoList(); + QFileInfoList files = testPath.entryInfoList(); + foreach(QFileInfo file, files) { + qDebug() << "My file: " + file.fileName(); + recursiveFileScan(file, &dirName); + } @@ -126,15 +132,15 @@ void FileScriptingInterface::unzipFile(QString path) { } void FileScriptingInterface::recursiveFileScan(QFileInfo file, QString* dirName) { - if (!file.isDir()) { + /*if (!file.isDir()) { qDebug() << "Regular file logged: " + file.fileName(); return; - } + }*/ QFileInfoList files; if (file.fileName().contains(".zip")) { + qDebug() << "Extracting archive: " + file.fileName(); JlCompress::extractDir(file.fileName()); - qDebug() << "Extracting archive: " + file.fileName(); } files = file.dir().entryInfoList(); diff --git a/scripts/system/examples.js b/scripts/system/examples.js index f67dd407bb..c445f218bc 100644 --- a/scripts/system/examples.js +++ b/scripts/system/examples.js @@ -12,8 +12,8 @@ var toolIconUrl = Script.resolvePath("assets/images/tools/"); //var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples"; -//var EXAMPLES_URL = "https://clara.io/view/c1c4d926-5648-4fd3-9673-6d9018ad4627"; -var EXAMPLES_URL = "http://s3.amazonaws.com/DreamingContent/test.html"; +var EXAMPLES_URL = "https://clara.io/view/c1c4d926-5648-4fd3-9673-6d9018ad4627"; +//var EXAMPLES_URL = "http://s3.amazonaws.com/DreamingContent/test.html"; //var EXAMPLES_URL = "https://hifi-content.s3.amazonaws.com/elisalj/test.html"; //var EXAMPLES_URL = "https://hifi-content.s3.amazonaws.com/elisalj/test_download.html"; From 615627e98138a82089385841e20d223447d12f2e Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Fri, 22 Jul 2016 15:33:58 -0700 Subject: [PATCH 038/134] Working download and unpackage from Clara.io --- interface/resources/qml/Browser.qml | 3 +++ interface/resources/qml/controls-uit/WebView.qml | 10 ++++++++++ interface/resources/qml/hifi/Desktop.qml | 14 ++++++++------ .../script-engine/src/FileScriptingInterface.cpp | 9 +++++---- scripts/system/examples.js | 3 ++- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index f3bdab74f4..833816972a 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -225,6 +225,9 @@ ScrollingWindow { Component.onCompleted: { desktop.initWebviewProfileHandlers(webview.profile) } + + + //profile: desktop.browserProfile diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index 5fa0f5f584..50ba2d92c3 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -25,6 +25,8 @@ WebEngineView { }); } + + // FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6 Timer { id: urlReplacementTimer @@ -68,9 +70,17 @@ WebEngineView { request.openIn(newWindow.webView); } + property var myScript: 'var element = $("a.download-file"); + element.removeClass("download-file"); + element.removeAttr("download _target");' + onLinkHovered: { desktop.currentUrl = hoveredUrl console.log("my url in WebView: " + desktop.currentUrl) + if (File.testUrl(desktop.currentUrl)) { + runJavaScript(myScript, function() {console.log("ran the JS"); }); + } + } // This breaks the webchannel used for passing messages. Fixed in Qt 5.6 diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 29f982887c..db501be031 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -19,7 +19,9 @@ OriginalDesktop.Desktop { scrollGestureEnabled: false // we don't need/want these onEntered: ApplicationCompositor.reticleOverDesktop = true onExited: ApplicationCompositor.reticleOverDesktop = false - acceptedButtons: Qt.NoButton + acceptedButtons: Qt.NoButtonMouseArea + + } // The tool window, one instance @@ -82,11 +84,11 @@ OriginalDesktop.Desktop { profile.downloadRequested.connect(function(download){ console.log("Download start: " + download.state) - if (!File.testUrl(currentUrl)) { - console.log("This file type is not accepted. Look for a zip file") - download.cancel() - return - } + //if (!File.testUrl(currentUrl)) { + //console.log("This file type is not accepted. Look for a zip file") + //download.cancel() + //return + //} adaptedPath = File.convertUrlToPath(currentUrl) download.path = "C:/Users/elisa/Downloads/" + adaptedPath console.log("Path where it should download: " + download.path) diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index ad4ae8bdc2..3a9cca64c4 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -38,7 +38,8 @@ void FileScriptingInterface::runUnzip(QString path, QUrl url) { } bool FileScriptingInterface::testUrl(QUrl url) { - if (url.toString().contains(".zip")) return true; + if (url.toString().contains(".zip") && url.toString().contains("fbx")) return true; + qDebug() << "This model is not a .fbx packaged in a .zip. Please try with another model."; return false; } @@ -80,14 +81,14 @@ void FileScriptingInterface::unzipFile(QString path) { //QString zipFileName = QFile::decodeName(compressedFileContent); QString dirName = dir.path(); - QDir testPath("C:/Users/elisa/Downloads/banana.zip"); + //QDir testPath("C:/Users/elisa/Downloads/banana.zip"); qDebug() << "Zip directory is stored at: " + dirName; - QStringList list = JlCompress::extractDir(testPath.path(), "C:/Users/elisa/Downloads/test"); + QStringList list = JlCompress::extractDir(dirName, "C:/Users/elisa/Downloads/test"); qDebug() << list; //QFileInfoList files = dir.entryInfoList(); - QFileInfoList files = testPath.entryInfoList(); + QFileInfoList files = dir.entryInfoList(); foreach(QFileInfo file, files) { qDebug() << "My file: " + file.fileName(); recursiveFileScan(file, &dirName); diff --git a/scripts/system/examples.js b/scripts/system/examples.js index c445f218bc..6c01fd58af 100644 --- a/scripts/system/examples.js +++ b/scripts/system/examples.js @@ -12,7 +12,8 @@ var toolIconUrl = Script.resolvePath("assets/images/tools/"); //var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples"; -var EXAMPLES_URL = "https://clara.io/view/c1c4d926-5648-4fd3-9673-6d9018ad4627"; +//var EXAMPLES_URL = "https://clara.io/view/c1c4d926-5648-4fd3-9673-6d9018ad4627"; +var EXAMPLES_URL = "https://clara.io/library"; //var EXAMPLES_URL = "http://s3.amazonaws.com/DreamingContent/test.html"; //var EXAMPLES_URL = "https://hifi-content.s3.amazonaws.com/elisalj/test.html"; //var EXAMPLES_URL = "https://hifi-content.s3.amazonaws.com/elisalj/test_download.html"; From a94a3047007e54a1ee5f24cf01e851d6a952efdb Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Mon, 25 Jul 2016 16:15:43 -0700 Subject: [PATCH 039/134] Downloads from Clara.io and uploads to asset server --- interface/resources/qml/AssetServer.qml | 1 + interface/src/Application.cpp | 6 +- .../src/FileScriptingInterface.cpp | 82 ++++++------------- .../src/FileScriptingInterface.h | 3 +- 4 files changed, 31 insertions(+), 61 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index 8d971e48d3..eca3d11721 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -320,6 +320,7 @@ ScrollingWindow { id: timer } function uploadClicked(fileUrl) { + console.log("Upload clicked url: " + fileUrl); if (uploadOpen) { return; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ccffceede0..7cf6410fd8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1543,7 +1543,10 @@ void Application::initializeUi() { rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance()); rootContext->setContextProperty("Controller", DependencyManager::get().data()); rootContext->setContextProperty("Entities", DependencyManager::get().data()); - rootContext->setContextProperty("File", new FileScriptingInterface(engine)); + //rootContext->setContextProperty("File", new FileScriptingInterface(engine)); + FileScriptingInterface* fileDownload = new FileScriptingInterface(engine); + rootContext->setContextProperty("File", fileDownload); + connect(fileDownload, &FileScriptingInterface::unzipSuccess, this, &Application::toggleAssetServerWidget); rootContext->setContextProperty("MyAvatar", getMyAvatar()); rootContext->setContextProperty("Messages", DependencyManager::get().data()); rootContext->setContextProperty("Recording", DependencyManager::get().data()); @@ -5035,6 +5038,7 @@ void Application::toggleAssetServerWidget(QString filePath) { auto startUpload = [=](QQmlContext* context, QObject* newObject){ if (!filePath.isEmpty()) { + qDebug() << "file in toggle: " + filePath; emit uploadRequest(filePath); } }; diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 3a9cca64c4..ac72b99c9f 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -34,7 +34,16 @@ FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent void FileScriptingInterface::runUnzip(QString path, QUrl url) { qDebug() << "Url that was downloaded: " + url.toString(); qDebug() << "Path where download is saved: " + path; - unzipFile(path); + QString file = unzipFile(path); + if (file != "") { + qDebug() << "file to upload: " + file; + QUrl url = QUrl::fromLocalFile(file); + qDebug() << "url from local file: " + url.toString(); + emit unzipSuccess(url.toString()); + //Application::toggleAssetServerWidget(file); + } else { + qDebug() << "unzip failed"; + } } bool FileScriptingInterface::testUrl(QUrl url) { @@ -68,67 +77,22 @@ void FileScriptingInterface::downloadZip(QString path, const QString link) { } // clement's help :D -void FileScriptingInterface::unzipFile(QString path) { - //ResourceRequest* request = qobject_cast(sender()); - //QUrl url = request->getUrl(); +QString FileScriptingInterface::unzipFile(QString path) { - //if (request->getResult() == ResourceRequest::Success) { - qDebug() << "Zip file was downloaded"; - QDir dir(path); - //QByteArray compressedFileContent = request->getData(); // <-- Downloaded file is in here - //QBuffer buffer(&compressedFileContent); - //buffer.open(QIODevice::ReadOnly); + qDebug() << "Zip file was downloaded"; + QDir dir(path); + QString dirName = dir.path(); + qDebug() << "Zip directory is stored at: " + dirName; + QStringList list = JlCompress::extractDir(dirName, "C:/Users/elisa/Downloads/test"); - //QString zipFileName = QFile::decodeName(compressedFileContent); - QString dirName = dir.path(); - //QDir testPath("C:/Users/elisa/Downloads/banana.zip"); - qDebug() << "Zip directory is stored at: " + dirName; - QStringList list = JlCompress::extractDir(dirName, "C:/Users/elisa/Downloads/test"); + qDebug() << list; - qDebug() << list; - - //QFileInfoList files = dir.entryInfoList(); - QFileInfoList files = dir.entryInfoList(); - foreach(QFileInfo file, files) { - qDebug() << "My file: " + file.fileName(); - recursiveFileScan(file, &dirName); - - } - - - /*foreach (QFileInfo file, files) { - if (file.isDir()) { - if (file.fileName().contains(".zip")) { - qDebug() << "Zip file expanded: " + file.fileName(); - } - - qDebug() << "Regular file logged: " + file.fileName(); - } - }*/ - - - - - //QFile file = - //need to convert this byte array to a file - /*QuaZip zip(zipFileName); - - if (zip.open(QuaZip::mdUnzip)) { - qDebug() << "Opened"; - - for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) { - // do something - qDebug() << zip.getCurrentFileName(); - } - if (zip.getZipError() == UNZ_OK) { - // ok, there was no error - }*/ - - - //buffer.close(); - //} else { - // qDebug() << "Could not download the zip file"; - //} + if (!list.isEmpty()) { + return list.front(); + } else { + qDebug() << "Extraction failed"; + return ""; + } } diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 6ba6044060..d90bf1ed2b 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -33,10 +33,11 @@ public slots: void runUnzip(QString path, QUrl url); signals: + void unzipSuccess(QString url); private: //void downloadZip(); - void unzipFile(QString path); + QString unzipFile(QString path); void recursiveFileScan(QFileInfo file, QString* dirName); void downloadZip(QString path, const QString link); From b1b2ea48b245d26e38a7cda88340f8718c51fd1e Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Tue, 26 Jul 2016 16:33:06 -0700 Subject: [PATCH 040/134] Made code more QA; extra browser and download widget close upon download --- interface/resources/qml/AssetServer.qml | 2 +- interface/resources/qml/Browser.qml | 7 -- .../resources/qml/controls-uit/WebView.qml | 54 ++++++--- interface/resources/qml/hifi/Desktop.qml | 69 +++++------ interface/src/Application.cpp | 40 ++----- interface/src/Application.h | 2 - .../scripting/WindowScriptingInterface.cpp | 14 --- .../src/scripting/WindowScriptingInterface.h | 1 - .../src/FileScriptingInterface.cpp | 109 +++++++++--------- .../src/FileScriptingInterface.h | 22 ++-- libraries/script-engine/src/ScriptEngine.cpp | 1 - libraries/ui/src/OffscreenUi.cpp | 3 - scripts/system/edit.js | 16 --- 13 files changed, 144 insertions(+), 196 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index eca3d11721..0f55e77a66 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -320,7 +320,7 @@ ScrollingWindow { id: timer } function uploadClicked(fileUrl) { - console.log("Upload clicked url: " + fileUrl); + console.log("Upload clicked url: " + fileUrl); if (uploadOpen) { return; } diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 833816972a..2be0ca176d 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -140,7 +140,6 @@ ScrollingWindow { } } -<<<<<<< ab02d16eb7656ea0a37785a398716fad62dff045 Rectangle { id:permissionsContainer visible:false @@ -197,8 +196,6 @@ ScrollingWindow { } } } -======= ->>>>>>> Zip download works WebEngineView { id: webview @@ -221,15 +218,11 @@ ScrollingWindow { onIconChanged: { console.log("New icon: " + icon) } - Component.onCompleted: { desktop.initWebviewProfileHandlers(webview.profile) } - - - //profile: desktop.browserProfile } diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index 50ba2d92c3..fdc1452d9b 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -25,7 +25,7 @@ WebEngineView { }); } - + // FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6 Timer { @@ -51,7 +51,7 @@ WebEngineView { onLoadingChanged: { // Required to support clicking on "hifi://" links - console.log("loading change requested url"); + console.log("loading change requested url"); if (WebEngineView.LoadStartedStatus == loadRequest.status) { var url = loadRequest.url.toString(); if (urlHandler.canHandleUrl(url)) { @@ -62,26 +62,44 @@ WebEngineView { } } - onNewViewRequested: { - console.log("new view requested url"); - //console.log("new view requested url" + request.url.toString()); - var component = Qt.createComponent("../Browser.qml"); - var newWindow = component.createObject(desktop); - request.openIn(newWindow.webView); + Timer { + id: zipTimer + running: false + repeat: false + interval: 1000 + property var handler; + onTriggered: handler(); } - property var myScript: 'var element = $("a.download-file"); - element.removeClass("download-file"); - element.removeAttr("download _target");' + property var autoCancel: 'var element = $("a.btn.cancel"); + element.click();' - onLinkHovered: { - desktop.currentUrl = hoveredUrl - console.log("my url in WebView: " + desktop.currentUrl) - if (File.testUrl(desktop.currentUrl)) { - runJavaScript(myScript, function() {console.log("ran the JS"); }); - } + onNewViewRequested: { + console.log("new view requested url"); + var component = Qt.createComponent("../Browser.qml"); + var newWindow = component.createObject(desktop); + request.openIn(newWindow.webView); + if (File.testUrl(desktop.currentUrl)) { + zipTimer.handler = function() { + newWindow.destroy(); + runJavaScript(autoCancel); + } + zipTimer.start(); + } + } - } + property var simpleDownload: 'var element = $("a.download-file"); + element.removeClass("download-file"); + element.removeAttr("download");' + + onLinkHovered: { + desktop.currentUrl = hoveredUrl + console.log("my url in WebView: " + desktop.currentUrl) + if (File.testUrl(desktop.currentUrl)) { + runJavaScript(simpleDownload, function(){console.log("ran the JS");}); + } + + } // This breaks the webchannel used for passing messages. Fixed in Qt 5.6 // See https://bugreports.qt.io/browse/QTBUG-49521 diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index db501be031..9ab9324b74 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -19,7 +19,7 @@ OriginalDesktop.Desktop { scrollGestureEnabled: false // we don't need/want these onEntered: ApplicationCompositor.reticleOverDesktop = true onExited: ApplicationCompositor.reticleOverDesktop = false - acceptedButtons: Qt.NoButtonMouseArea + acceptedButtons: Qt.NoButton } @@ -73,44 +73,39 @@ OriginalDesktop.Desktop { }); } - // Accept a download through the webview - property bool webViewProfileSetup: false - property string currentUrl: "" - property string adaptedPath: "" - function initWebviewProfileHandlers(profile) { - console.log("the webview url in desktop is: " + currentUrl) - if (webViewProfileSetup) return; - webViewProfileSetup = true; + // Accept a download through the webview + property bool webViewProfileSetup: false + property string currentUrl: "" + property string adaptedPath: "" - profile.downloadRequested.connect(function(download){ - console.log("Download start: " + download.state) - //if (!File.testUrl(currentUrl)) { - //console.log("This file type is not accepted. Look for a zip file") - //download.cancel() - //return - //} - adaptedPath = File.convertUrlToPath(currentUrl) - download.path = "C:/Users/elisa/Downloads/" + adaptedPath - console.log("Path where it should download: " + download.path) - download.accept() - console.log("Download accept: " + download.state) - if (download.state === WebEngineDownloadItem.DownloadInterrupted) { - console.log("Download? " + download.state) - console.log("download failed to complete") - } - }) + function initWebviewProfileHandlers(profile) { + console.log("the webview url in desktop is: " + currentUrl); + if (webViewProfileSetup) return; + webViewProfileSetup = true; - profile.downloadFinished.connect(function(download){ - if (download.state === WebEngineDownloadItem.DownloadCompleted) { - console.log("Download Finished: " + download.state) - console.log("File object is: " + File) - File.runUnzip(download.path, currentUrl) - //download.cancel() - } else { - console.log("The download was corrupted, state: " + download.state) - } - }) - } + profile.downloadRequested.connect(function(download){ + console.log("Download start: " + download.state); + adaptedPath = File.convertUrlToPath(currentUrl); + download.path = "C:/Users/elisa/Downloads/" + adaptedPath; + console.log("Path where it should download: " + download.path); + download.accept(); + console.log("Download accept: " + download.state); + if (download.state === WebEngineDownloadItem.DownloadInterrupted) { + console.log("Download? " + download.state); + console.log("download failed to complete"); + } + }) + + profile.downloadFinished.connect(function(download){ + if (download.state === WebEngineDownloadItem.DownloadCompleted) { + console.log("Download Finished: " + download.state); + console.log("File object is: " + File); + File.runUnzip(download.path, currentUrl); + } else { + console.log("The download was corrupted, state: " + download.state); + } + }) + } // Create or fetch a toolbar with the given name function getToolbar(name) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7cf6410fd8..66fb6ed6b6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -355,7 +355,6 @@ public: if (message->message == WM_COPYDATA) { COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)(message->lParam); - qDebug() << "os windows url for some reason"; QUrl url = QUrl((const char*)(pcds->lpData)); if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) { DependencyManager::get()->handleLookupString(url.toString()); @@ -1543,10 +1542,9 @@ void Application::initializeUi() { rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance()); rootContext->setContextProperty("Controller", DependencyManager::get().data()); rootContext->setContextProperty("Entities", DependencyManager::get().data()); - //rootContext->setContextProperty("File", new FileScriptingInterface(engine)); - FileScriptingInterface* fileDownload = new FileScriptingInterface(engine); - rootContext->setContextProperty("File", fileDownload); - connect(fileDownload, &FileScriptingInterface::unzipSuccess, this, &Application::toggleAssetServerWidget); + FileScriptingInterface* fileDownload = new FileScriptingInterface(engine); + rootContext->setContextProperty("File", fileDownload); + connect(fileDownload, &FileScriptingInterface::unzipSuccess, this, &Application::toggleAssetServerWidget); rootContext->setContextProperty("MyAvatar", getMyAvatar()); rootContext->setContextProperty("Messages", DependencyManager::get().data()); rootContext->setContextProperty("Recording", DependencyManager::get().data()); @@ -2020,14 +2018,6 @@ bool Application::importSVOFromURL(const QString& urlString) { return true; } -// attempt to start ZIP download project -bool Application::importZIPFromURL(const QString& urlString) { - qDebug() << "zip import request has been emitted"; - emit zipImportRequested(urlString); - return true; -} -// end attempt - bool Application::event(QEvent* event) { if (!Menu::getInstance()) { @@ -2147,26 +2137,21 @@ bool Application::event(QEvent* event) { // handle custom URL if (event->type() == QEvent::FileOpen) { - qDebug() << "we have received one url!: "; QFileOpenEvent* fileEvent = static_cast(event); QUrl url = fileEvent->url(); if (!url.isEmpty()) { QString urlString = url.toString(); - qDebug() << "we got a url!: " + urlString; + if (canAcceptURL(urlString)) { - qDebug() << "we got an ACCEPTED url!: " + urlString; + return acceptURL(urlString); } } return false; } - if (event->type() == QEvent::None) { - qDebug() << "this url just didn't click"; - } - if (HFActionEvent::types().contains(event->type())) { _controllerScriptingInterface->handleMetaEvent(static_cast(event)); } @@ -3190,7 +3175,6 @@ void Application::saveSettings() const { } bool Application::importEntities(const QString& urlOrFilename) { - qDebug() << "import entities url"; bool success = false; _entityClipboard->withWriteLock([&] { _entityClipboard->eraseAllOctreeElements(); @@ -4800,7 +4784,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri } bool Application::canAcceptURL(const QString& urlString) const { - qDebug() << "stepping through 'canAcceptURL'"; QUrl url(urlString); if (urlString.startsWith(HIFI_URL_SCHEME)) { return true; @@ -4817,7 +4800,6 @@ bool Application::canAcceptURL(const QString& urlString) const { } bool Application::acceptURL(const QString& urlString, bool defaultUpload) { - qDebug() << "stepping through 'acceptURL'"; if (urlString.startsWith(HIFI_URL_SCHEME)) { // this is a hifi URL - have the AddressManager handle it QMetaObject::invokeMethod(DependencyManager::get().data(), "handleLookupString", @@ -4847,7 +4829,6 @@ void Application::setSessionUUID(const QUuid& sessionUUID) const { } bool Application::askToSetAvatarUrl(const QString& url) { - qDebug() << "setting avatar url"; QUrl realUrl(url); if (realUrl.isLocalFile()) { OffscreenUi::warning("", "You can not use local files for avatar components."); @@ -4904,7 +4885,6 @@ bool Application::askToSetAvatarUrl(const QString& url) { bool Application::askToLoadScript(const QString& scriptFilenameOrURL) { - qDebug() << "setting script url"; QMessageBox::StandardButton reply; QString shortName = scriptFilenameOrURL; @@ -4929,7 +4909,6 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) { } bool Application::askToWearAvatarAttachmentUrl(const QString& url) { - qDebug() << "setting avatar attachment url"; QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest = QNetworkRequest(url); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); @@ -5011,7 +4990,6 @@ bool Application::displayAvatarAttachmentConfirmationDialog(const QString& name) } void Application::toggleRunningScriptsWidget() const { - qDebug() << "toggle running scripts url"; static const QUrl url("hifi/dialogs/RunningScripts.qml"); DependencyManager::get()->show(url, "RunningScripts"); //if (_runningScriptsWidget->isVisible()) { @@ -5029,16 +5007,16 @@ void Application::toggleRunningScriptsWidget() const { } void Application::toggleAssetServerWidget(QString filePath) { - qDebug() << "toggle asset before if"; + qDebug() << "toggle asset before if: " + filePath; if (!DependencyManager::get()->getThisNodeCanWriteAssets()) { return; } - qDebug() << "toggle asset after if"; + qDebug() << "toggle asset after if"; static const QUrl url { "AssetServer.qml" }; auto startUpload = [=](QQmlContext* context, QObject* newObject){ if (!filePath.isEmpty()) { - qDebug() << "file in toggle: " + filePath; + qDebug() << "file in toggle: " + filePath; emit uploadRequest(filePath); } }; @@ -5051,7 +5029,6 @@ void Application::packageModel() { } void Application::openUrl(const QUrl& url) const { - qDebug() << "open url"; if (!url.isEmpty()) { if (url.scheme() == HIFI_URL_SCHEME) { DependencyManager::get()->handleLookupString(url.toString()); @@ -5082,7 +5059,6 @@ void Application::setPreviousScriptLocation(const QString& location) { } void Application::loadScriptURLDialog() const { - qDebug() << "load script url dialog"; auto newScript = OffscreenUi::getText(nullptr, "Open and Run Script", "Script URL"); if (!newScript.isEmpty()) { DependencyManager::get()->loadScript(newScript); diff --git a/interface/src/Application.h b/interface/src/Application.h index d8f02f41b7..0af65f665f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -250,7 +250,6 @@ public: signals: void svoImportRequested(const QString& url); - void zipImportRequested(const QString& url); void fullAvatarURLChanged(const QString& newValue, const QString& modelName); @@ -386,7 +385,6 @@ private: bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); - bool importZIPFromURL(const QString& urlString); bool nearbyEntitiesAreReadyForPhysics(); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 2ea562143e..b165cda135 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -59,20 +59,6 @@ WindowScriptingInterface::WindowScriptingInterface() { OffscreenUi::warning("Import SVO Error", "You need to be running edit.js to import entities."); } }); - // attempt to start ZIP download project - connect(qApp, &Application::zipImportRequested, [this](const QString& urlString) { - qDebug() << "zip import has been requested"; - static const QMetaMethod zipImportRequestedSignal = - QMetaMethod::fromSignal(&WindowScriptingInterface::zipImportRequested); - - if (isSignalConnected(zipImportRequestedSignal)) { - QUrl url(urlString); - emit zipImportRequested(url.url()); - } else { - OffscreenUi::warning("Import ZIP Error", "You need to be running edit.js to import entities."); - } - // end attempt - }); } WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index b33da4ef4d..9d73111333 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -58,7 +58,6 @@ public slots: signals: void domainChanged(const QString& domainHostname); void svoImportRequested(const QString& url); - void zipImportRequested(const QString& url); // zip project void domainConnectionRefused(const QString& reasonMessage, int reasonCode); void snapshotTaken(const QString& path); diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index ac72b99c9f..4126b5fdad 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -28,94 +28,97 @@ FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent) { - // nothing for now + // nothing for now } void FileScriptingInterface::runUnzip(QString path, QUrl url) { - qDebug() << "Url that was downloaded: " + url.toString(); - qDebug() << "Path where download is saved: " + path; - QString file = unzipFile(path); - if (file != "") { - qDebug() << "file to upload: " + file; - QUrl url = QUrl::fromLocalFile(file); - qDebug() << "url from local file: " + url.toString(); - emit unzipSuccess(url.toString()); - //Application::toggleAssetServerWidget(file); - } else { - qDebug() << "unzip failed"; - } + qDebug() << "Url that was downloaded: " + url.toString(); + qDebug() << "Path where download is saved: " + path; + QString file = unzipFile(path); + if (file != "") { + qDebug() << "file to upload: " + file; + QUrl url = QUrl::fromLocalFile(file); + qDebug() << "url from local file: " + url.toString(); + emit unzipSuccess(url.toString()); + } else { + qDebug() << "unzip failed"; + } } bool FileScriptingInterface::testUrl(QUrl url) { - if (url.toString().contains(".zip") && url.toString().contains("fbx")) return true; - qDebug() << "This model is not a .fbx packaged in a .zip. Please try with another model."; - return false; + if (url.toString().contains(".zip") && url.toString().contains("fbx")) return true; + qDebug() << "This model is not a .fbx packaged in a .zip. Please try with another model."; + return false; } +// this function is not in use QString FileScriptingInterface::getTempDir() { - QTemporaryDir dir; - dir.setAutoRemove(false); - return dir.path(); - // remember I must do something to delete this temp dir later + QTemporaryDir dir; + dir.setAutoRemove(false); + return dir.path(); + // do something to delete this temp dir later } QString FileScriptingInterface::convertUrlToPath(QUrl url) { - QString newUrl; - QString oldUrl = url.toString(); - newUrl = oldUrl.section("filename=", 1, 1); - qDebug() << "Filename should be: " + newUrl; - return newUrl; + QString newUrl; + QString oldUrl = url.toString(); + newUrl = oldUrl.section("filename=", 1, 1); + qDebug() << "Filename should be: " + newUrl; + return newUrl; } +// this function is not in use void FileScriptingInterface::downloadZip(QString path, const QString link) { - QUrl url = QUrl(link); - auto request = ResourceManager::createResourceRequest(nullptr, url); - connect(request, &ResourceRequest::finished, this, [this, path]{ - unzipFile(path); - }); + QUrl url = QUrl(link); + auto request = ResourceManager::createResourceRequest(nullptr, url); + connect(request, &ResourceRequest::finished, this, [this, path]{ + unzipFile(path); + }); request->send(); } -// clement's help :D + QString FileScriptingInterface::unzipFile(QString path) { - qDebug() << "Zip file was downloaded"; - QDir dir(path); + QDir dir(path); QString dirName = dir.path(); - qDebug() << "Zip directory is stored at: " + dirName; + qDebug() << "Zip directory is stored at: " + dirName; + QString target = path.section("/", -1) + "/model_repo"; + qDebug() << "Target path: " + target; QStringList list = JlCompress::extractDir(dirName, "C:/Users/elisa/Downloads/test"); - qDebug() << list; + qDebug() << list; - if (!list.isEmpty()) { - return list.front(); - } else { - qDebug() << "Extraction failed"; - return ""; - } + if (!list.isEmpty()) { + return list.front(); + } else { + qDebug() << "Extraction failed"; + return ""; + } } +// this function is not in use void FileScriptingInterface::recursiveFileScan(QFileInfo file, QString* dirName) { - /*if (!file.isDir()) { - qDebug() << "Regular file logged: " + file.fileName(); - return; - }*/ + /*if (!file.isDir()) { + qDebug() << "Regular file logged: " + file.fileName(); + return; + }*/ QFileInfoList files; - if (file.fileName().contains(".zip")) { - qDebug() << "Extracting archive: " + file.fileName(); - JlCompress::extractDir(file.fileName()); + if (file.fileName().contains(".zip")) { + qDebug() << "Extracting archive: " + file.fileName(); + JlCompress::extractDir(file.fileName()); } files = file.dir().entryInfoList(); - /*if (files.empty()) { - files = JlCompress::getFileList(file.fileName()); - }*/ + /*if (files.empty()) { + files = JlCompress::getFileList(file.fileName()); + }*/ - foreach (QFileInfo file, files) { + foreach (QFileInfo file, files) { qDebug() << "Looking into file: " + file.fileName(); recursiveFileScan(file, dirName); - } + } return; } diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index d90bf1ed2b..df6b91c678 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -22,24 +22,24 @@ class FileScriptingInterface : public QObject { public: FileScriptingInterface(QObject* parent); - //void runUnzip(QString path, QString importURL); - QString getTempDir(); + //void runUnzip(QString path, QString importURL); + QString getTempDir(); public slots: - //void unzipFile(QString path); - bool testUrl(QUrl url); - QString convertUrlToPath(QUrl url); - void runUnzip(QString path, QUrl url); + //void unzipFile(QString path); + bool testUrl(QUrl url); + QString convertUrlToPath(QUrl url); + void runUnzip(QString path, QUrl url); signals: - void unzipSuccess(QString url); + void unzipSuccess(QString url); private: - //void downloadZip(); - QString unzipFile(QString path); - void recursiveFileScan(QFileInfo file, QString* dirName); - void downloadZip(QString path, const QString link); + //void downloadZip(); + QString unzipFile(QString path); + void recursiveFileScan(QFileInfo file, QString* dirName); + void downloadZip(QString path, const QString link); }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index fe7e1c4036..dd3fcad749 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -503,7 +503,6 @@ void ScriptEngine::init() { registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("Messages", DependencyManager::get().data()); - // unzip project registerGlobalObject("File", new FileScriptingInterface(this)); qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 82a9186f92..06ef456006 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -78,20 +78,17 @@ class UrlHandler : public QObject { Q_OBJECT public: Q_INVOKABLE bool canHandleUrl(const QString& url) { - qDebug() << Q_FUNC_INFO; static auto handler = dynamic_cast(qApp); return handler->canAcceptURL(url); } Q_INVOKABLE bool handleUrl(const QString& url) { - qDebug() << Q_FUNC_INFO; static auto handler = dynamic_cast(qApp); return handler->acceptURL(url); } // FIXME hack for authentication, remove when we migrate to Qt 5.6 Q_INVOKABLE QString fixupUrl(const QString& originalUrl) { - qDebug() << Q_FUNC_INFO; return fixupHifiUrl(originalUrl); } }; diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 1284202c6d..25c25a9a7e 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1205,22 +1205,6 @@ function importSVO(importURL) { } Window.svoImportRequested.connect(importSVO); -// attempt to start ZIP download project, GET RID OF THIS -function importZIP(importURL) { - print("Import ZIP requested: " + importURL); - /*if (!Entities.canAdjustLocks()) { - Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); - return; - }*/ - var path = File.getTempDir(); - print("Temporary path to zip: " + path); - File.runUnzip(path, importURL); - - -} -Window.zipImportRequested.connect(importZIP); -//end attempt - Menu.menuItemEvent.connect(handeMenuEvent); Controller.keyPressEvent.connect(function (event) { From a9a8710689022e1e36f1d07bed282a885505828a Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Tue, 26 Jul 2016 17:47:54 -0700 Subject: [PATCH 041/134] Switched saving download/upload to temporary directory --- interface/resources/qml/controls-uit/WebView.qml | 2 +- interface/resources/qml/hifi/Desktop.qml | 7 ++++--- .../script-engine/src/FileScriptingInterface.cpp | 14 ++++++++------ .../script-engine/src/FileScriptingInterface.h | 10 +++------- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index fdc1452d9b..bb08e5e389 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -66,7 +66,7 @@ WebEngineView { id: zipTimer running: false repeat: false - interval: 1000 + interval: 1500 property var handler; onTriggered: handler(); } diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 9ab9324b74..ab1fffdcf5 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -77,6 +77,7 @@ OriginalDesktop.Desktop { property bool webViewProfileSetup: false property string currentUrl: "" property string adaptedPath: "" + property string tempDir: "" function initWebviewProfileHandlers(profile) { console.log("the webview url in desktop is: " + currentUrl); @@ -86,12 +87,12 @@ OriginalDesktop.Desktop { profile.downloadRequested.connect(function(download){ console.log("Download start: " + download.state); adaptedPath = File.convertUrlToPath(currentUrl); - download.path = "C:/Users/elisa/Downloads/" + adaptedPath; + tempDir = File.getTempDir(); + download.path = tempDir + "/" + adaptedPath; console.log("Path where it should download: " + download.path); download.accept(); console.log("Download accept: " + download.state); if (download.state === WebEngineDownloadItem.DownloadInterrupted) { - console.log("Download? " + download.state); console.log("download failed to complete"); } }) @@ -100,7 +101,7 @@ OriginalDesktop.Desktop { if (download.state === WebEngineDownloadItem.DownloadCompleted) { console.log("Download Finished: " + download.state); console.log("File object is: " + File); - File.runUnzip(download.path, currentUrl); + File.runUnzip(download.path, tempDir, currentUrl); } else { console.log("The download was corrupted, state: " + download.state); } diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 4126b5fdad..94d8d1b424 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -31,10 +31,10 @@ FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent // nothing for now } -void FileScriptingInterface::runUnzip(QString path, QUrl url) { +void FileScriptingInterface::runUnzip(QString path, QString tempDir, QUrl url) { qDebug() << "Url that was downloaded: " + url.toString(); qDebug() << "Path where download is saved: " + path; - QString file = unzipFile(path); + QString file = unzipFile(path, tempDir); if (file != "") { qDebug() << "file to upload: " + file; QUrl url = QUrl::fromLocalFile(file); @@ -43,6 +43,8 @@ void FileScriptingInterface::runUnzip(QString path, QUrl url) { } else { qDebug() << "unzip failed"; } + qDebug() << "Removing temporary directory at: " + tempDir; + QDir(tempDir).removeRecursively(); } bool FileScriptingInterface::testUrl(QUrl url) { @@ -72,20 +74,20 @@ void FileScriptingInterface::downloadZip(QString path, const QString link) { QUrl url = QUrl(link); auto request = ResourceManager::createResourceRequest(nullptr, url); connect(request, &ResourceRequest::finished, this, [this, path]{ - unzipFile(path); + unzipFile(path, ""); // so intellisense isn't mad }); request->send(); } -QString FileScriptingInterface::unzipFile(QString path) { +QString FileScriptingInterface::unzipFile(QString path, QString tempDir) { QDir dir(path); QString dirName = dir.path(); qDebug() << "Zip directory is stored at: " + dirName; - QString target = path.section("/", -1) + "/model_repo"; + QString target = tempDir + "/model_repo"; qDebug() << "Target path: " + target; - QStringList list = JlCompress::extractDir(dirName, "C:/Users/elisa/Downloads/test"); + QStringList list = JlCompress::extractDir(dirName, target); qDebug() << list; diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index df6b91c678..2658622644 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -22,22 +22,18 @@ class FileScriptingInterface : public QObject { public: FileScriptingInterface(QObject* parent); - //void runUnzip(QString path, QString importURL); - QString getTempDir(); - public slots: - //void unzipFile(QString path); bool testUrl(QUrl url); QString convertUrlToPath(QUrl url); - void runUnzip(QString path, QUrl url); + void runUnzip(QString path, QString tempDir, QUrl url); + QString getTempDir(); signals: void unzipSuccess(QString url); private: - //void downloadZip(); - QString unzipFile(QString path); + QString unzipFile(QString path, QString tempDir); void recursiveFileScan(QFileInfo file, QString* dirName); void downloadZip(QString path, const QString link); From cd7706e80b2831ed0f4bd17155d74ed1439f994e Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Thu, 28 Jul 2016 13:56:38 -0700 Subject: [PATCH 042/134] Release now has quazip features --- cmake/externals/quazip/CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index bf51a52fc5..d8ab492be5 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -37,11 +37,14 @@ set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${${EXTERNAL_NAME_UPPER}_INCLUDE_DIR} CA set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/lib CACHE FILEPATH "Location of QuaZip DLL") if (APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5d.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library") elseif (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5.lib CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library") else () - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library") endif () include(SelectLibraryConfigurations) From d63d0ba870a6ffac8be96b6458b7457bfdbbdaef Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Wed, 3 Aug 2016 14:16:39 -0700 Subject: [PATCH 043/134] In process of creating combobox for marketplace with qml --- interface/resources/qml/QmlWindow.qml | 10 ++- .../resources/qml/controls-uit/ComboBox.qml | 1 + .../resources/qml/controls-uit/Label.qml | 1 + .../qml/controls-uit/MarketplaceComboBox.qml | 43 ++++++++++ scripts/system/marketplace - Elisa.js | 82 +++++++++++++++++++ scripts/system/marketplace.js | 1 + 6 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 interface/resources/qml/controls-uit/MarketplaceComboBox.qml create mode 100644 scripts/system/marketplace - Elisa.js diff --git a/interface/resources/qml/QmlWindow.qml b/interface/resources/qml/QmlWindow.qml index 7be747a3ad..47857ac7c1 100644 --- a/interface/resources/qml/QmlWindow.qml +++ b/interface/resources/qml/QmlWindow.qml @@ -1,13 +1,16 @@ -import QtQuick 2.3 -import QtQuick.Controls 1.2 +import QtQuick 2.5 +import QtQuick.Controls 1.4 import QtWebChannel 1.0 +import QtWebEngine 1.1 import QtWebSockets 1.0 import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel import "windows" as Windows import "controls" +import "controls-uit" as Controls import "styles" +import "styles-uit" Windows.Window { id: root @@ -23,6 +26,8 @@ Windows.Window { property var eventBridge; property var component; property var dynamicContent; + + onSourceChanged: { if (dynamicContent) { dynamicContent.destroy(); @@ -71,5 +76,6 @@ Windows.Window { Item { id: contentHolder anchors.fill: parent + } } diff --git a/interface/resources/qml/controls-uit/ComboBox.qml b/interface/resources/qml/controls-uit/ComboBox.qml index eb0c08624b..fa100a965f 100644 --- a/interface/resources/qml/controls-uit/ComboBox.qml +++ b/interface/resources/qml/controls-uit/ComboBox.qml @@ -18,6 +18,7 @@ import "." as VrControls FocusScope { id: root + HifiConstants { id: hifi } property alias model: comboBox.model; property alias comboBox: comboBox diff --git a/interface/resources/qml/controls-uit/Label.qml b/interface/resources/qml/controls-uit/Label.qml index 3b4d757154..330d74fa14 100644 --- a/interface/resources/qml/controls-uit/Label.qml +++ b/interface/resources/qml/controls-uit/Label.qml @@ -13,6 +13,7 @@ import QtQuick 2.5 import "../styles-uit" RalewaySemiBold { + HifiConstants { id: hifi } property int colorScheme: hifi.colorSchemes.light size: hifi.fontSizes.inputLabel diff --git a/interface/resources/qml/controls-uit/MarketplaceComboBox.qml b/interface/resources/qml/controls-uit/MarketplaceComboBox.qml new file mode 100644 index 0000000000..986131f3ec --- /dev/null +++ b/interface/resources/qml/controls-uit/MarketplaceComboBox.qml @@ -0,0 +1,43 @@ +// +// MarketplaceComboBox.qml +// +// Created by Elisa Lupin-Jimenez on 3 Aug 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtWebChannel 1.0 +import QtWebEngine 1.1 +import QtWebSockets 1.0 +import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel + +import "controls" +import "controls-uit" as Controls +import "styles" +import "styles-uit" + +// just temporary + Controls.WebView { + id: webview + anchors.fill: parent + url: "about:blank" + focus: true + } + + Controls.ComboBox { + id: switchMarketView + //anchors.top: parent.bottom + //anchors.bottomMargin: 4 + anchors.fill: parent + visible: true + model: ListModel { + id: cbItems + ListElement { text: "Banana" } + ListElement { text: "Apple" } + ListElement { text: "Coconut" } + } + } diff --git a/scripts/system/marketplace - Elisa.js b/scripts/system/marketplace - Elisa.js new file mode 100644 index 0000000000..7a4057d77b --- /dev/null +++ b/scripts/system/marketplace - Elisa.js @@ -0,0 +1,82 @@ +// +// marketplace.js +// +// Created by Eric Levin on 8 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var toolIconUrl = Script.resolvePath("assets/images/tools/"); + +var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; +var CLARA_URL = "https://clara.io/library"; +var marketplaceWindow = new OverlayWindow({ + title: "Marketplace", + source: "about:blank", + //source: MARKETPLACE_URL, + //source: "https://s3.amazonaws.com/DreamingContent/qml/content.qml", + //source: "C:\Users\elisa\Documents\GitHub\hifi\interface\resources\qml\controls-uit\WebView.qml", + width: 900, + height: 700, + toolWindow: false, + visible: false, +}); + +var toolHeight = 50; +var toolWidth = 50; +var TOOLBAR_MARGIN_Y = 0; + + +function showMarketplace(marketplaceID) { + var url = MARKETPLACE_URL; + if (marketplaceID) { + url = url + "/items/" + marketplaceID; + } + marketplaceWindow.setVisible(true); + //marketplaceWindow.webview.url = url; + + UserActivityLogger.openedMarketplace(); +} + +function hideMarketplace() { + marketplaceWindow.setVisible(false); + marketplaceWindow.webview.url = "about:blank"; +} + +function toggleMarketplace() { + if (marketplaceWindow.visible) { + hideMarketplace(); + } else { + showMarketplace(); + } +} + +var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + +var browseExamplesButton = toolBar.addButton({ + imageURL: toolIconUrl + "market.svg", + objectName: "marketplace", + buttonState: 1, + defaultState: 1, + hoverState: 3, + alpha: 0.9 +}); + +function onExamplesWindowVisibilityChanged() { + browseExamplesButton.writeProperty('buttonState', marketplaceWindow.visible ? 0 : 1); + browseExamplesButton.writeProperty('defaultState', marketplaceWindow.visible ? 0 : 1); + browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3); +} +function onClick() { + toggleMarketplace(); +} +browseExamplesButton.clicked.connect(onClick); +marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); + +Script.scriptEnding.connect(function () { + toolBar.removeButton("marketplace"); + browseExamplesButton.clicked.disconnect(onClick); + marketplaceWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); +}); diff --git a/scripts/system/marketplace.js b/scripts/system/marketplace.js index 356ed8e8cf..e83e0c2ccb 100644 --- a/scripts/system/marketplace.js +++ b/scripts/system/marketplace.js @@ -11,6 +11,7 @@ var toolIconUrl = Script.resolvePath("assets/images/tools/"); var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; + var marketplaceWindow = new OverlayWebWindow({ title: "Marketplace", source: "about:blank", From b39c8c52abe0e722ac62cc1170a8abf706c05681 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Wed, 3 Aug 2016 19:08:14 -0700 Subject: [PATCH 044/134] Included combobox in marketplace view --- .../resources/qml/MarketplaceComboBox.qml | 52 +++++++++++++++++++ interface/resources/qml/QmlWindow.qml | 1 - .../qml/controls-uit/MarketplaceComboBox.qml | 43 --------------- scripts/system/marketplace - Elisa.js | 9 ++-- 4 files changed, 56 insertions(+), 49 deletions(-) create mode 100644 interface/resources/qml/MarketplaceComboBox.qml delete mode 100644 interface/resources/qml/controls-uit/MarketplaceComboBox.qml diff --git a/interface/resources/qml/MarketplaceComboBox.qml b/interface/resources/qml/MarketplaceComboBox.qml new file mode 100644 index 0000000000..21a7d48556 --- /dev/null +++ b/interface/resources/qml/MarketplaceComboBox.qml @@ -0,0 +1,52 @@ +// +// MarketplaceComboBox.qml +// +// Created by Elisa Lupin-Jimenez on 3 Aug 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtWebChannel 1.0 +import QtWebEngine 1.1 +import QtWebSockets 1.0 +import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel + +import "controls" +import "controls-uit" as Controls +import "styles" +import "styles-uit" + +Item { + id: marketplaceComboBox + anchors.fill: parent + property var currentUrl: "https://metaverse.highfidelity.com/marketplace" + Controls.WebView { + id: webview + url: currentUrl + anchors.top: parent.top + width: parent.width + height: parent.height - 50 + //anchors.bottom: switchMarketView.top + focus: true + } + + Controls.ComboBox { + id: switchMarketView + anchors.bottom: parent.bottom + width: parent.width + height: 50 + visible: true + label: "Market View: " + model: ["Marketplace", "Clara.io"] + onCurrentIndexChanged: { + if (currentIndex === 0) { webview.url = "https://metaverse.highfidelity.com/marketplace"; } + if (currentIndex === 1) { webview.url = "https://clara.io/library"; } + } + + } + +} \ No newline at end of file diff --git a/interface/resources/qml/QmlWindow.qml b/interface/resources/qml/QmlWindow.qml index 47857ac7c1..908c1b1a77 100644 --- a/interface/resources/qml/QmlWindow.qml +++ b/interface/resources/qml/QmlWindow.qml @@ -76,6 +76,5 @@ Windows.Window { Item { id: contentHolder anchors.fill: parent - } } diff --git a/interface/resources/qml/controls-uit/MarketplaceComboBox.qml b/interface/resources/qml/controls-uit/MarketplaceComboBox.qml deleted file mode 100644 index 986131f3ec..0000000000 --- a/interface/resources/qml/controls-uit/MarketplaceComboBox.qml +++ /dev/null @@ -1,43 +0,0 @@ -// -// MarketplaceComboBox.qml -// -// Created by Elisa Lupin-Jimenez on 3 Aug 2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtWebChannel 1.0 -import QtWebEngine 1.1 -import QtWebSockets 1.0 -import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel - -import "controls" -import "controls-uit" as Controls -import "styles" -import "styles-uit" - -// just temporary - Controls.WebView { - id: webview - anchors.fill: parent - url: "about:blank" - focus: true - } - - Controls.ComboBox { - id: switchMarketView - //anchors.top: parent.bottom - //anchors.bottomMargin: 4 - anchors.fill: parent - visible: true - model: ListModel { - id: cbItems - ListElement { text: "Banana" } - ListElement { text: "Apple" } - ListElement { text: "Coconut" } - } - } diff --git a/scripts/system/marketplace - Elisa.js b/scripts/system/marketplace - Elisa.js index 7a4057d77b..baec825c8d 100644 --- a/scripts/system/marketplace - Elisa.js +++ b/scripts/system/marketplace - Elisa.js @@ -9,15 +9,14 @@ // var toolIconUrl = Script.resolvePath("assets/images/tools/"); +var qml = Script.resolvePath("../../interface/resources/qml/MarketplaceComboBox.qml") var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; var CLARA_URL = "https://clara.io/library"; var marketplaceWindow = new OverlayWindow({ title: "Marketplace", - source: "about:blank", - //source: MARKETPLACE_URL, - //source: "https://s3.amazonaws.com/DreamingContent/qml/content.qml", - //source: "C:\Users\elisa\Documents\GitHub\hifi\interface\resources\qml\controls-uit\WebView.qml", + //source: "about:blank", + source: qml, width: 900, height: 700, toolWindow: false, @@ -42,7 +41,7 @@ function showMarketplace(marketplaceID) { function hideMarketplace() { marketplaceWindow.setVisible(false); - marketplaceWindow.webview.url = "about:blank"; + //marketplaceWindow.webview.url = "about:blank"; } function toggleMarketplace() { From 90a1325f65aadf0466fbd81d9d69cb47798accba Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Thu, 4 Aug 2016 15:45:16 -0700 Subject: [PATCH 045/134] Finalized combobox feature --- .../resources/qml/MarketplaceComboBox.qml | 25 ++++-- scripts/system/marketplace - Elisa.js | 81 ------------------- scripts/system/marketplace.js | 10 +-- 3 files changed, 22 insertions(+), 94 deletions(-) delete mode 100644 scripts/system/marketplace - Elisa.js diff --git a/interface/resources/qml/MarketplaceComboBox.qml b/interface/resources/qml/MarketplaceComboBox.qml index 21a7d48556..da9a994bcc 100644 --- a/interface/resources/qml/MarketplaceComboBox.qml +++ b/interface/resources/qml/MarketplaceComboBox.qml @@ -20,27 +20,28 @@ import "controls-uit" as Controls import "styles" import "styles-uit" -Item { +Rectangle { + HifiConstants { id: hifi } id: marketplaceComboBox anchors.fill: parent + color: hifi.colors.baseGrayShadow property var currentUrl: "https://metaverse.highfidelity.com/marketplace" Controls.WebView { id: webview url: currentUrl - anchors.top: parent.top + anchors.top: switchMarketView.bottom width: parent.width - height: parent.height - 50 - //anchors.bottom: switchMarketView.top + height: parent.height - 40 focus: true } Controls.ComboBox { id: switchMarketView - anchors.bottom: parent.bottom - width: parent.width - height: 50 + anchors.top: parent.top + anchors.right: parent.right + width: 200 + height: 40 visible: true - label: "Market View: " model: ["Marketplace", "Clara.io"] onCurrentIndexChanged: { if (currentIndex === 0) { webview.url = "https://metaverse.highfidelity.com/marketplace"; } @@ -49,4 +50,12 @@ Item { } + Controls.Label { + id: switchMarketLabel + anchors.verticalCenter: switchMarketView.verticalCenter + anchors.right: switchMarketView.left + color: hifi.colors.white + text: "Explore interesting content from: " + } + } \ No newline at end of file diff --git a/scripts/system/marketplace - Elisa.js b/scripts/system/marketplace - Elisa.js deleted file mode 100644 index baec825c8d..0000000000 --- a/scripts/system/marketplace - Elisa.js +++ /dev/null @@ -1,81 +0,0 @@ -// -// marketplace.js -// -// Created by Eric Levin on 8 Jan 2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var toolIconUrl = Script.resolvePath("assets/images/tools/"); -var qml = Script.resolvePath("../../interface/resources/qml/MarketplaceComboBox.qml") - -var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; -var CLARA_URL = "https://clara.io/library"; -var marketplaceWindow = new OverlayWindow({ - title: "Marketplace", - //source: "about:blank", - source: qml, - width: 900, - height: 700, - toolWindow: false, - visible: false, -}); - -var toolHeight = 50; -var toolWidth = 50; -var TOOLBAR_MARGIN_Y = 0; - - -function showMarketplace(marketplaceID) { - var url = MARKETPLACE_URL; - if (marketplaceID) { - url = url + "/items/" + marketplaceID; - } - marketplaceWindow.setVisible(true); - //marketplaceWindow.webview.url = url; - - UserActivityLogger.openedMarketplace(); -} - -function hideMarketplace() { - marketplaceWindow.setVisible(false); - //marketplaceWindow.webview.url = "about:blank"; -} - -function toggleMarketplace() { - if (marketplaceWindow.visible) { - hideMarketplace(); - } else { - showMarketplace(); - } -} - -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - -var browseExamplesButton = toolBar.addButton({ - imageURL: toolIconUrl + "market.svg", - objectName: "marketplace", - buttonState: 1, - defaultState: 1, - hoverState: 3, - alpha: 0.9 -}); - -function onExamplesWindowVisibilityChanged() { - browseExamplesButton.writeProperty('buttonState', marketplaceWindow.visible ? 0 : 1); - browseExamplesButton.writeProperty('defaultState', marketplaceWindow.visible ? 0 : 1); - browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3); -} -function onClick() { - toggleMarketplace(); -} -browseExamplesButton.clicked.connect(onClick); -marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); - -Script.scriptEnding.connect(function () { - toolBar.removeButton("marketplace"); - browseExamplesButton.clicked.disconnect(onClick); - marketplaceWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); -}); diff --git a/scripts/system/marketplace.js b/scripts/system/marketplace.js index e83e0c2ccb..01aa4c76ce 100644 --- a/scripts/system/marketplace.js +++ b/scripts/system/marketplace.js @@ -9,15 +9,17 @@ // var toolIconUrl = Script.resolvePath("assets/images/tools/"); +var qml = Script.resolvePath("../../resources/qml/MarketplaceComboBox.qml") var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; -var marketplaceWindow = new OverlayWebWindow({ +var marketplaceWindow = new OverlayWindow({ title: "Marketplace", - source: "about:blank", + source: qml, width: 900, height: 700, - visible: false + toolWindow: false, + visible: false, }); var toolHeight = 50; @@ -30,7 +32,6 @@ function showMarketplace(marketplaceID) { if (marketplaceID) { url = url + "/items/" + marketplaceID; } - marketplaceWindow.setURL(url); marketplaceWindow.setVisible(true); UserActivityLogger.openedMarketplace(); @@ -38,7 +39,6 @@ function showMarketplace(marketplaceID) { function hideMarketplace() { marketplaceWindow.setVisible(false); - marketplaceWindow.setURL("about:blank"); } function toggleMarketplace() { From e8c5303f1b933508c3736717ff3182def37cbdb8 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Thu, 4 Aug 2016 17:23:36 -0700 Subject: [PATCH 046/134] Removed examples.js --- scripts/system/examples.js | 80 -------------------------------------- 1 file changed, 80 deletions(-) delete mode 100644 scripts/system/examples.js diff --git a/scripts/system/examples.js b/scripts/system/examples.js deleted file mode 100644 index 6c01fd58af..0000000000 --- a/scripts/system/examples.js +++ /dev/null @@ -1,80 +0,0 @@ -// -// examples.js -// examples -// -// Created by Eric Levin on 8 Jan 2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var toolIconUrl = Script.resolvePath("assets/images/tools/"); - -//var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples"; -//var EXAMPLES_URL = "https://clara.io/view/c1c4d926-5648-4fd3-9673-6d9018ad4627"; -var EXAMPLES_URL = "https://clara.io/library"; -//var EXAMPLES_URL = "http://s3.amazonaws.com/DreamingContent/test.html"; -//var EXAMPLES_URL = "https://hifi-content.s3.amazonaws.com/elisalj/test.html"; -//var EXAMPLES_URL = "https://hifi-content.s3.amazonaws.com/elisalj/test_download.html"; - -var examplesWindow = new OverlayWebWindow({ - title: 'Examples', - source: "about:blank", - width: 900, - height: 700, - visible: false -}); - -var toolHeight = 50; -var toolWidth = 50; -var TOOLBAR_MARGIN_Y = 0; - - -function showExamples(marketplaceID) { - var url = EXAMPLES_URL; - if (marketplaceID) { - url = url + "/items/" + marketplaceID; - } - print("setting examples URL to " + url); - examplesWindow.setURL(url); - examplesWindow.setVisible(true); - - UserActivityLogger.openedMarketplace(); -} - -function hideExamples() { - examplesWindow.setVisible(false); - examplesWindow.setURL("about:blank"); -} - -function toggleExamples() { - if (examplesWindow.visible) { - hideExamples(); - } else { - showExamples(); - } -} - -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - -var browseExamplesButton = toolBar.addButton({ - imageURL: toolIconUrl + "market.svg", - objectName: "examples", - buttonState: 1, - alpha: 0.9 -}); - -function onExamplesWindowVisibilityChanged() { - browseExamplesButton.writeProperty('buttonState', examplesWindow.visible ? 0 : 1); -} -function onClick() { - toggleExamples(); -} -browseExamplesButton.clicked.connect(onClick); -examplesWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); - -Script.scriptEnding.connect(function () { - browseExamplesButton.clicked.disconnect(onClick); - examplesWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); -}); From c00983468579621c551dd2e1d0fbd5d42d84878d Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Fri, 5 Aug 2016 17:36:27 -0700 Subject: [PATCH 047/134] Fixes for linux build of quazip --- cmake/externals/quazip/CMakeLists.txt | 2 +- interface/resources/qml/MarketplaceComboBox.qml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index d8ab492be5..f00403640a 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -17,7 +17,7 @@ ExternalProject_Add( URL https://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.7.2.zip URL_MD5 2955176048a31262c09259ca8d309d19 BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=/lib -DZLIB_ROOT=${ZLIB_ROOT} + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 diff --git a/interface/resources/qml/MarketplaceComboBox.qml b/interface/resources/qml/MarketplaceComboBox.qml index da9a994bcc..d0c55c9fe7 100644 --- a/interface/resources/qml/MarketplaceComboBox.qml +++ b/interface/resources/qml/MarketplaceComboBox.qml @@ -39,6 +39,7 @@ Rectangle { id: switchMarketView anchors.top: parent.top anchors.right: parent.right + colorScheme: hifi.colorSchemes.dark width: 200 height: 40 visible: true From c8f3a898d25824291982c52261de3a4cddfaecfd Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 5 Aug 2016 10:51:51 -0700 Subject: [PATCH 048/134] First cut of a snapshot uploader Will need to test end-to-end shortly, etc... --- interface/src/Application.cpp | 5 ++ interface/src/Application.h | 1 + .../scripting/WindowScriptingInterface.cpp | 8 +- .../src/scripting/WindowScriptingInterface.h | 2 + interface/src/ui/Snapshot.cpp | 88 +++++++++++++++++++ interface/src/ui/Snapshot.h | 11 +++ scripts/system/snapshot.js | 13 ++- 7 files changed, 126 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index baddc26301..5be03a5e4f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5082,6 +5082,11 @@ void Application::takeSnapshot(bool notify) { emit DependencyManager::get()->snapshotTaken(path, notify); } +void Application::shareSnapshot(const QString& path) { + // not much to do here, everything is done in snapshot code... + Snapshot::uploadSnapshot(path); +} + float Application::getRenderResolutionScale() const { if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) { return 1.0f; diff --git a/interface/src/Application.h b/interface/src/Application.h index ea6a117cfa..aa3244c53a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -249,6 +249,7 @@ public: float getAverageSimsPerSecond() const { return _simCounter.rate(); } void takeSnapshot(bool notify); + void shareSnapshot(const QString& filename); signals: void svoImportRequested(const QString& url); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 026818ec82..9ce0b5bca5 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -202,7 +202,13 @@ void WindowScriptingInterface::copyToClipboard(const QString& text) { void WindowScriptingInterface::takeSnapshot(bool notify) { // only evil-doers call takeSnapshot from a random thread - qApp->postLambdaEvent([&] { + qApp->postLambdaEvent([notify] { qApp->takeSnapshot(notify); }); } + +void WindowScriptingInterface::shareSnapshot(const QString& path) { + qApp->postLambdaEvent([path] { + qApp->shareSnapshot(path); + }); +} diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 1abcb9db35..24f2a619ce 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -55,12 +55,14 @@ public slots: QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); void copyToClipboard(const QString& text); void takeSnapshot(bool notify); + void shareSnapshot(const QString& path); signals: void domainChanged(const QString& domainHostname); void svoImportRequested(const QString& url); void domainConnectionRefused(const QString& reasonMessage, int reasonCode); void snapshotTaken(const QString& path, bool notify); + void snapshotShared(bool success); private slots: WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index aaf11d14a4..42ee4fa2f5 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -32,6 +32,7 @@ #include "Application.h" #include "Snapshot.h" +#include "scripting/WindowScriptingInterface.h" // filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg // %1 <= username, %2 <= date and time, %3 <= current location @@ -141,3 +142,90 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) { return imageTempFile; } } + +void Snapshot::uploadSnapshot(const QString& filename) { + + const QString SNAPSHOT_UPLOAD_URL = "/api/v1/snapshots"; + static SnapshotUploader uploader; + + qDebug() << "uploading snapshot " << filename; + + QFile* file = new QFile(filename); + Q_ASSERT(file->exists()); + file->open(QIODevice::ReadOnly); + + QHttpPart imagePart; + imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, + QVariant("form-data; name=\"image\"; filename=\"" + file->fileName() + "\"")); + imagePart.setBodyDevice(file); + + QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart + multiPart->append(imagePart); + + auto accountManager = DependencyManager::get(); + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = &uploader; + callbackParams.jsonCallbackMethod = "uploadSuccess"; + callbackParams.errorCallbackReceiver = &uploader; + callbackParams.errorCallbackMethod = "uploadFailure"; + + accountManager->sendRequest(SNAPSHOT_UPLOAD_URL, + AccountManagerAuth::Required, + QNetworkAccessManager::PostOperation, + callbackParams, + nullptr, + multiPart); +} + +void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { + const QString STORY_UPLOAD_URL = "/api/v1/user_stories"; + static SnapshotUploader uploader; + + // parse the reply for the thumbnail_url + QByteArray contents = reply.readAll(); + QJsonParseError jsonError; + auto doc = QJsonDocument::fromJson(contents, &jsonError); + if (jsonError.error == QJsonParseError::NoError) { + QString thumbnail_url = doc.object().value("thumbnail_url").toString(); + + // create json post data + QJsonObject rootObject; + QJsonObject userStoryObject; + userStoryObject.insert("thumbnail_url", thumbnail_url); + userStoryObject.insert("action", "snapshot"); + rootObject.insert("user_story", userStoryObject); + + auto accountManager = DependencyManager::get(); + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = &uploader; + callbackParams.jsonCallbackMethod = "createStorySuccess"; + callbackParams.errorCallbackReceiver = &uploader; + callbackParams.errorCallbackMethod = "createStoryFailure"; + + accountManager->sendRequest(STORY_UPLOAD_URL, + AccountManagerAuth::Required, + QNetworkAccessManager::PostOperation, + callbackParams, + QJsonDocument(rootObject).toJson()); + + } else { + qDebug() << "Error parsing upload response: " << jsonError.errorString(); + emit DependencyManager::get()->snapshotShared(false); + } +} + +void SnapshotUploader::uploadFailure(QNetworkReply& reply) { + // TODO: parse response, potentially helpful for logging (?) + emit DependencyManager::get()->snapshotShared(false); +} + +void SnapshotUploader::createStorySuccess(QNetworkReply& reply) { + emit DependencyManager::get()->snapshotShared(true); +} + +void SnapshotUploader::createStoryFailure(QNetworkReply& reply) { + // TODO: parse response, potentially helpful for logging (?) + emit DependencyManager::get()->snapshotShared(false); +} diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 2e7986a5c0..e780537b76 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -32,6 +32,16 @@ private: QUrl _URL; }; + +class SnapshotUploader: public QObject { + Q_OBJECT +public slots: + void uploadSuccess(QNetworkReply& reply); + void uploadFailure(QNetworkReply& reply); + void createStorySuccess(QNetworkReply& reply); + void createStoryFailure(QNetworkReply& reply); +}; + class Snapshot { public: static QString saveSnapshot(QImage image); @@ -40,6 +50,7 @@ public: static Setting::Handle snapshotsLocation; static Setting::Handle hasSetSnapshotsLocation; + static void uploadSnapshot(const QString& filename); private: static QFile* savedFileForSnapshot(QImage & image, bool isTemporary); }; diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 92ce36e935..8a6b811085 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -24,7 +24,18 @@ function confirmShare(data) { if (!Window.confirm("Share snapshot " + data.localPath + "?")) { // This dialog will be more elaborate... return; } - Window.alert("Pretending to upload. That code will go here."); + Window.snapshotShared.connect(snapshotShared); + Window.shareSnapshot(data.localPath); +} + +function snapshotShared(success) { + if(success) { + // for now just print status + print('snapshot uploaded and shared'); + } else { + // for now just print an error. + print('snapshot upload/share failed'); + } } function onClicked() { From f34030d276421e3e48be7afa6f837c04a09df994 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 9 Aug 2016 12:48:01 -0700 Subject: [PATCH 049/134] factor out metaverseBase to make it easier to repoint to a test server --- interface/resources/qml/AddressBarDialog.qml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 5883872c95..8590121fa0 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -55,6 +55,7 @@ Window { property var allStories: []; property int cardWidth: 200; property int cardHeight: 152; + property string metaverseBase: "https://metaverse.highfidelity.com/api/v1/"; function pastTime(timestamp) { // Answer a descriptive string timestamp = new Date(timestamp); var then = timestamp.getTime(), @@ -292,7 +293,7 @@ Window { } function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description - var url = 'https://metaverse.highfidelity.com/api/v1/places/' + placeData.place_name; + var url = metaverseBase + 'places/' + placeData.place_name; getRequest(url, function (error, data) { if (handleError(url, error, data, cb)) { return; @@ -361,7 +362,7 @@ Window { 'sort_order=desc', 'page=' + pageNumber ]; - var url = 'https://metaverse.highfidelity.com/api/v1/domains/all?' + params.join('&'); + var url = metaverseBase + 'domains/all?' + params.join('&'); getRequest(url, function (error, data) { if (handleError(url, error, data, cb)) { return; @@ -389,7 +390,7 @@ Window { }); } function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model - var url = 'https://metaverse.highfidelity.com/api/v1/user_stories?page=' + pageNumber; + var url = metaverseBase + 'user_stories?page=' + pageNumber; getRequest(url, function (error, data) { if (handleError(url, error, data, cb)) { return; From 8457acd234c0ffd52ec7fbc781a9c33304de510c Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 9 Aug 2016 13:42:48 -0700 Subject: [PATCH 050/134] First guess on how to deal with place Fall back to host when there is no place. Probably better ideas, like specify the name and the type (a place, a domain if no place, etc...) will come soon. --- interface/src/ui/Snapshot.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 42ee4fa2f5..71e7d1a703 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -188,12 +188,17 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { QJsonParseError jsonError; auto doc = QJsonDocument::fromJson(contents, &jsonError); if (jsonError.error == QJsonParseError::NoError) { - QString thumbnail_url = doc.object().value("thumbnail_url").toString(); + QString thumbnailUrl = doc.object().value("thumbnail_url").toString(); + QString placeName = DependencyManager::get()->getPlaceName(); + if(placeName.isEmpty()) { + placeName = DependencyManager::get()->getHost(); + } // create json post data QJsonObject rootObject; QJsonObject userStoryObject; - userStoryObject.insert("thumbnail_url", thumbnail_url); + userStoryObject.insert("thumbnail_url", thumbnailUrl); + userStoryObject.insert("place_name", placeName); userStoryObject.insert("action", "snapshot"); rootObject.insert("user_story", userStoryObject); From 18990821df2f209bcc62441a1cf7424ad69ccac3 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 9 Aug 2016 14:15:49 -0700 Subject: [PATCH 051/134] Added 'path' to user stories, works now. yay --- interface/src/ui/Snapshot.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 71e7d1a703..e15182934b 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -189,16 +189,19 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { auto doc = QJsonDocument::fromJson(contents, &jsonError); if (jsonError.error == QJsonParseError::NoError) { QString thumbnailUrl = doc.object().value("thumbnail_url").toString(); - QString placeName = DependencyManager::get()->getPlaceName(); + auto addressManager = DependencyManager::get(); + QString placeName = addressManager->getPlaceName(); if(placeName.isEmpty()) { - placeName = DependencyManager::get()->getHost(); + placeName = addressManager->getHost(); } + QString currentPath = addressManager->currentPath(true); // create json post data QJsonObject rootObject; QJsonObject userStoryObject; userStoryObject.insert("thumbnail_url", thumbnailUrl); userStoryObject.insert("place_name", placeName); + userStoryObject.insert("path", currentPath); userStoryObject.insert("action", "snapshot"); rootObject.insert("user_story", userStoryObject); From d4f376879d38011e1cca5d4029404b19848e09d4 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 9 Aug 2016 15:05:23 -0700 Subject: [PATCH 052/134] PR feedback --- interface/src/ui/Snapshot.cpp | 17 +++-------------- scripts/system/snapshot.js | 2 +- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index e15182934b..f6bd8e2db9 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -148,8 +148,6 @@ void Snapshot::uploadSnapshot(const QString& filename) { const QString SNAPSHOT_UPLOAD_URL = "/api/v1/snapshots"; static SnapshotUploader uploader; - qDebug() << "uploading snapshot " << filename; - QFile* file = new QFile(filename); Q_ASSERT(file->exists()); file->open(QIODevice::ReadOnly); @@ -165,11 +163,7 @@ void Snapshot::uploadSnapshot(const QString& filename) { multiPart->append(imagePart); auto accountManager = DependencyManager::get(); - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = &uploader; - callbackParams.jsonCallbackMethod = "uploadSuccess"; - callbackParams.errorCallbackReceiver = &uploader; - callbackParams.errorCallbackMethod = "uploadFailure"; + JSONCallbackParameters callbackParams(&uploader, "uploadSuccess", &uploader, "uploadFailure"); accountManager->sendRequest(SNAPSHOT_UPLOAD_URL, AccountManagerAuth::Required, @@ -191,7 +185,7 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { QString thumbnailUrl = doc.object().value("thumbnail_url").toString(); auto addressManager = DependencyManager::get(); QString placeName = addressManager->getPlaceName(); - if(placeName.isEmpty()) { + if (placeName.isEmpty()) { placeName = addressManager->getHost(); } QString currentPath = addressManager->currentPath(true); @@ -206,11 +200,7 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { rootObject.insert("user_story", userStoryObject); auto accountManager = DependencyManager::get(); - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = &uploader; - callbackParams.jsonCallbackMethod = "createStorySuccess"; - callbackParams.errorCallbackReceiver = &uploader; - callbackParams.errorCallbackMethod = "createStoryFailure"; + JSONCallbackParameters callbackParams(&uploader, "createStorySuccess", &uploader, "createStoryFailure"); accountManager->sendRequest(STORY_UPLOAD_URL, AccountManagerAuth::Required, @@ -219,7 +209,6 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { QJsonDocument(rootObject).toJson()); } else { - qDebug() << "Error parsing upload response: " << jsonError.errorString(); emit DependencyManager::get()->snapshotShared(false); } } diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 8a6b811085..ac92a06749 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -29,7 +29,7 @@ function confirmShare(data) { } function snapshotShared(success) { - if(success) { + if (success) { // for now just print status print('snapshot uploaded and shared'); } else { From 5715fd00f312877395d0feeb2ddc898b8f4b8403 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 9 Aug 2016 16:42:41 -0700 Subject: [PATCH 053/134] proper share dialog --- scripts/system/html/ShareSnapshot.html | 78 ++++++++++++++++++++++++++ scripts/system/snapshot.js | 28 +++++++-- 2 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 scripts/system/html/ShareSnapshot.html diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/ShareSnapshot.html new file mode 100644 index 0000000000..4691b7488c --- /dev/null +++ b/scripts/system/html/ShareSnapshot.html @@ -0,0 +1,78 @@ + + + Share + + + + + + + + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ + diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 61345254be..84019e68cc 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -21,11 +21,27 @@ var button = toolBar.addButton({ }); function confirmShare(data) { - if (!Window.confirm("Share snapshot " + data.localPath + "?")) { // This dialog will be more elaborate... - return; + var dialog = new OverlayWebWindow('Snapshot', Script.resolvePath("html/ShareSnapshot.html"), 800, 300); + function onMessage(message) { + if (message == 'ready') { // The window can now receive data from us. + dialog.emitScriptEvent(data); // Send it. + return; + } // Rest is confirmation processing + dialog.webEventReceived.disconnect(onMessage); // I'm not certain that this is necessary. If it is, what do we do on normal close? + dialog.close(); + dialog.deleteLater(); + message = message.filter(function (picture) { return picture.share; }); + if (message.length) { + print('sharing', message.map(function (picture) { return picture.localPath; }).join(', ')); + message.forEach(function (data) { + Window.shareSnapshot(data.localPath); + }); + } else { + print('declined to share', JSON.stringify(data)); + } } - Window.snapshotShared.connect(snapshotShared); - Window.shareSnapshot(data.localPath); + dialog.webEventReceived.connect(onMessage); + dialog.raise(); } function snapshotShared(success) { @@ -74,12 +90,14 @@ function resetButtons(path, notify) { button.writeProperty("defaultState", 1); button.writeProperty("hoverState", 3); Window.snapshotTaken.disconnect(resetButtons); - confirmShare({localPath: path}); + confirmShare([{localPath: path}]); } button.clicked.connect(onClicked); +Window.snapshotShared.connect(snapshotShared); Script.scriptEnding.connect(function () { toolBar.removeButton("snapshot"); button.clicked.disconnect(onClicked); + Window.snapshotShared.disconnect(snapshotShared); }); From b8f5a9d22f79239f9c643847fb8ba523417fd011 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Wed, 10 Aug 2016 10:26:58 -0700 Subject: [PATCH 054/134] CR changes --- interface/resources/qml/Browser.qml | 6 +-- .../resources/qml/MarketplaceComboBox.qml | 42 +++++++++++++++++++ interface/resources/qml/QmlWindow.qml | 2 +- .../resources/qml/controls-uit/WebView.qml | 38 ----------------- 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 2be0ca176d..3693b9dfea 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -218,9 +218,9 @@ ScrollingWindow { onIconChanged: { console.log("New icon: " + icon) } - Component.onCompleted: { - desktop.initWebviewProfileHandlers(webview.profile) - } + Component.onCompleted: { + desktop.initWebviewProfileHandlers(webview.profile) + } //profile: desktop.browserProfile diff --git a/interface/resources/qml/MarketplaceComboBox.qml b/interface/resources/qml/MarketplaceComboBox.qml index d0c55c9fe7..e7981cabec 100644 --- a/interface/resources/qml/MarketplaceComboBox.qml +++ b/interface/resources/qml/MarketplaceComboBox.qml @@ -20,12 +20,14 @@ import "controls-uit" as Controls import "styles" import "styles-uit" + Rectangle { HifiConstants { id: hifi } id: marketplaceComboBox anchors.fill: parent color: hifi.colors.baseGrayShadow property var currentUrl: "https://metaverse.highfidelity.com/marketplace" + Controls.WebView { id: webview url: currentUrl @@ -33,6 +35,46 @@ Rectangle { width: parent.width height: parent.height - 40 focus: true + + Timer { + id: zipTimer + running: false + repeat: false + interval: 1500 + property var handler; + onTriggered: handler(); + } + + property var autoCancel: 'var element = $("a.btn.cancel"); + element.click();' + + onNewViewRequested: { + console.log("new view requested url"); + var component = Qt.createComponent("Browser.qml"); + var newWindow = component.createObject(desktop); + request.openIn(newWindow.webView); + if (File.testUrl(desktop.currentUrl)) { + zipTimer.handler = function() { + newWindow.destroy(); + runJavaScript(autoCancel); + } + zipTimer.start(); + } + } + + property var simpleDownload: 'var element = $("a.download-file"); + element.removeClass("download-file"); + element.removeAttr("download");' + + onLinkHovered: { + desktop.currentUrl = hoveredUrl + console.log("my url in WebView: " + desktop.currentUrl) + if (File.testUrl(desktop.currentUrl)) { + runJavaScript(simpleDownload, function(){console.log("ran the JS");}); + } + + } + } Controls.ComboBox { diff --git a/interface/resources/qml/QmlWindow.qml b/interface/resources/qml/QmlWindow.qml index 908c1b1a77..ac6ae31c7f 100644 --- a/interface/resources/qml/QmlWindow.qml +++ b/interface/resources/qml/QmlWindow.qml @@ -1,5 +1,5 @@ -import QtQuick 2.5 +import QtQuick 2.3 import QtQuick.Controls 1.4 import QtWebChannel 1.0 import QtWebEngine 1.1 diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index bb08e5e389..8069ee79fb 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -62,44 +62,6 @@ WebEngineView { } } - Timer { - id: zipTimer - running: false - repeat: false - interval: 1500 - property var handler; - onTriggered: handler(); - } - - property var autoCancel: 'var element = $("a.btn.cancel"); - element.click();' - - onNewViewRequested: { - console.log("new view requested url"); - var component = Qt.createComponent("../Browser.qml"); - var newWindow = component.createObject(desktop); - request.openIn(newWindow.webView); - if (File.testUrl(desktop.currentUrl)) { - zipTimer.handler = function() { - newWindow.destroy(); - runJavaScript(autoCancel); - } - zipTimer.start(); - } - } - - property var simpleDownload: 'var element = $("a.download-file"); - element.removeClass("download-file"); - element.removeAttr("download");' - - onLinkHovered: { - desktop.currentUrl = hoveredUrl - console.log("my url in WebView: " + desktop.currentUrl) - if (File.testUrl(desktop.currentUrl)) { - runJavaScript(simpleDownload, function(){console.log("ran the JS");}); - } - - } // This breaks the webchannel used for passing messages. Fixed in Qt 5.6 // See https://bugreports.qt.io/browse/QTBUG-49521 From f8f99721c3fdd606885db7285c592fbc6ca4e3b0 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 10 Aug 2016 14:25:00 -0700 Subject: [PATCH 055/134] Minor update to add details And, now reflects data-web's slightly updated json structure for returning info on an uploaded snapshot. --- interface/src/ui/Snapshot.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index f6bd8e2db9..beb86af1c4 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -182,7 +182,9 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { QJsonParseError jsonError; auto doc = QJsonDocument::fromJson(contents, &jsonError); if (jsonError.error == QJsonParseError::NoError) { - QString thumbnailUrl = doc.object().value("thumbnail_url").toString(); + auto dataObject = doc.object().value("data").toObject(); + QString thumbnailUrl = dataObject.value("thumbnail_url").toString(); + QString imageUrl = dataObject.value("image_url").toString(); auto addressManager = DependencyManager::get(); QString placeName = addressManager->getPlaceName(); if (placeName.isEmpty()) { @@ -193,6 +195,9 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { // create json post data QJsonObject rootObject; QJsonObject userStoryObject; + QJsonObject detailsObject; + detailsObject.insert("image_url", imageUrl); + userStoryObject.insert("details", detailsObject); userStoryObject.insert("thumbnail_url", thumbnailUrl); userStoryObject.insert("place_name", placeName); userStoryObject.insert("path", currentPath); From 5c15b520404ed1afb3e66d02bbd28803c5426719 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 10 Aug 2016 14:54:29 -0700 Subject: [PATCH 056/134] expose getPlaceName() as placename Nice for scripts to get the placename. Nice for us, anyways. --- libraries/networking/src/AddressManager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 2e9f177137..0315d749c4 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -38,6 +38,7 @@ class AddressManager : public QObject, public Dependency { Q_PROPERTY(QString protocol READ getProtocol) Q_PROPERTY(QString hostname READ getHost) Q_PROPERTY(QString pathname READ currentPath) + Q_PROPERTY(QString placename READ getPlaceName) public: Q_INVOKABLE QString protocolVersion(); using PositionGetter = std::function; From 47dea0ea2b60ae1f06b940e5cbf30892e99da94f Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 10 Aug 2016 17:09:43 -0700 Subject: [PATCH 057/134] Hide sharing if not logged in, or in an accessible place The grand future will have option to login, and so on... --- scripts/system/html/ShareSnapshot.html | 25 ++++++++++++++++++++----- scripts/system/snapshot.js | 8 +++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/ShareSnapshot.html index 4691b7488c..d838a01e99 100644 --- a/scripts/system/html/ShareSnapshot.html +++ b/scripts/system/html/ShareSnapshot.html @@ -28,16 +28,29 @@ paths.push(data); } + function handleShareButtons(canShare) { + if (!canShare) { + // hide the share/do not share buttons + document.getElementById("sharing").innerHTML = "

You can share if you are logged in and in a public place"; + } + } window.onload = function () { // Something like the following will allow testing in a browser. //addImage({localPath: 'c:/Users/howar/OneDrive/Pictures/hifi-snap-by--on-2016-07-27_12-58-43.jpg'}); openEventBridge(function () { // Set up a handler for receiving the data, and tell the .js we are ready to receive it. EventBridge.scriptEventReceived.connect(function (message) { + // last element of list contains a bool for whether or not we can share stuff + var canShare = message.pop().canShare; + print("canShare:"+canShare+", message:" + message.toString()) + handleShareButtons(canShare); + + // rest are image paths which we add message.forEach(addImage); }); EventBridge.emitWebEvent('ready'); }); + }; // beware of bug: Cannot send objects at top level. (Nested in arrays is fine.) shareSelected = function() { @@ -64,11 +77,13 @@

-
- -
-
- +
+
+ +
+
+ +
diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 84019e68cc..0acb5d5acf 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -77,6 +77,10 @@ function onClicked() { }, SNAPSHOT_DELAY); } +function canShare() { + return Account.isLoggedIn() && Boolean(Window.location.placename); +} + function resetButtons(path, notify) { // show overlays if they were on if (resetOverlays) { @@ -90,7 +94,9 @@ function resetButtons(path, notify) { button.writeProperty("defaultState", 1); button.writeProperty("hoverState", 3); Window.snapshotTaken.disconnect(resetButtons); - confirmShare([{localPath: path}]); + + // last element in data array tells dialog whether we can share or not + confirmShare([ { localPath: path }, { canShare: canShare() } ]); } button.clicked.connect(onClicked); From c1edd008a4f77eeb26fff9f7f95b7dc727d032cc Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 11 Aug 2016 11:47:55 -0700 Subject: [PATCH 058/134] PR feedback --- scripts/system/html/ShareSnapshot.html | 25 +++++++++++++++---------- scripts/system/snapshot.js | 9 ++++----- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/ShareSnapshot.html index d838a01e99..d41da0fb7a 100644 --- a/scripts/system/html/ShareSnapshot.html +++ b/scripts/system/html/ShareSnapshot.html @@ -28,10 +28,16 @@ paths.push(data); } - function handleShareButtons(canShare) { - if (!canShare) { - // hide the share/do not share buttons - document.getElementById("sharing").innerHTML = "

You can share if you are logged in and in a public place"; + function handleShareButtons(shareMsg) { + if (!shareMsg.canShare) { + // this means you may or may not be logged in, but can't share + // because you are not in a public place. + document.getElementById("sharing").innerHTML = "

You can share if you are in a public place"; + } else if (!shareMsg.isLoggedIn) { + // this means you are in a public place, but can't share because + // you need to login. Soon we will just bring up the share dialog + // in this case (and maybe set a boolean here to inform the html) + document.getElementById("sharing").innerHTML = "

You can share if you are logged in"; } } window.onload = function () { @@ -41,9 +47,8 @@ // Set up a handler for receiving the data, and tell the .js we are ready to receive it. EventBridge.scriptEventReceived.connect(function (message) { // last element of list contains a bool for whether or not we can share stuff - var canShare = message.pop().canShare; - print("canShare:"+canShare+", message:" + message.toString()) - handleShareButtons(canShare); + var shareMsg = message.pop(); + handleShareButtons(shareMsg); // rest are image paths which we add message.forEach(addImage); @@ -74,10 +79,10 @@

-
- -
+
+ +
diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 0acb5d5acf..4c0ba37ab3 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -77,10 +77,6 @@ function onClicked() { }, SNAPSHOT_DELAY); } -function canShare() { - return Account.isLoggedIn() && Boolean(Window.location.placename); -} - function resetButtons(path, notify) { // show overlays if they were on if (resetOverlays) { @@ -96,7 +92,10 @@ function resetButtons(path, notify) { Window.snapshotTaken.disconnect(resetButtons); // last element in data array tells dialog whether we can share or not - confirmShare([ { localPath: path }, { canShare: canShare() } ]); + confirmShare([ + { localPath: path }, + { canShare: Boolean(Window.location.placename), isLoggedIn: Account.isLoggedIn() } + ]); } button.clicked.connect(onClicked); From e3aae0e93f0e2a2d55bbbd6055efaf6c313e9a1b Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 11 Aug 2016 16:23:01 -0700 Subject: [PATCH 059/134] Fix up layout, and adapt to recent changes in file structure --- scripts/system/html/ShareSnapshot.html | 71 +++++++++++++++++++------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/ShareSnapshot.html index 4691b7488c..fd865cfb7a 100644 --- a/scripts/system/html/ShareSnapshot.html +++ b/scripts/system/html/ShareSnapshot.html @@ -1,9 +1,48 @@ Share - + + - + - + -
-
-
+
+
+
-
+
-
+
-
+
-
+
+
-
From 747c43d0656d0ec33050d3079ab2c55c490e18a0 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 11 Aug 2016 16:43:29 -0700 Subject: [PATCH 060/134] basic user story card --- interface/resources/qml/AddressBarDialog.qml | 63 ++++++++------ .../resources/qml/controls-uit/Button.qml | 2 + interface/resources/qml/hifi/Card.qml | 51 ++++++++++-- .../resources/qml/hifi/UserStoryCard.qml | 83 +++++++++++++++++++ 4 files changed, 167 insertions(+), 32 deletions(-) create mode 100644 interface/resources/qml/hifi/UserStoryCard.qml diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 8590121fa0..a65a228cf8 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -47,7 +47,16 @@ Window { } function goCard(card) { - addressLine.text = card.path; + if (useFeed) { + storyCard.imageUrl = card.imageUrl; //"http://howard-stearns.github.io/models/images/dancing-avatars.jpg"; + storyCard.userName = card.userName; + storyCard.placeName = card.placeName; + storyCard.actionPhrase = card.actionPhrase; + storyCard.timePhrase = card.timePhrase; + storyCard.visible = true; + return; + } + addressLine.text = card.hifiUrl; toggleOrGo(true); } property bool useFeed: false; @@ -56,26 +65,6 @@ Window { property int cardWidth: 200; property int cardHeight: 152; property string metaverseBase: "https://metaverse.highfidelity.com/api/v1/"; - function pastTime(timestamp) { // Answer a descriptive string - timestamp = new Date(timestamp); - var then = timestamp.getTime(), - now = Date.now(), - since = now - then, - ONE_MINUTE = 1000 * 60, - ONE_HOUR = ONE_MINUTE * 60, - hours = since / ONE_HOUR, - minutes = (hours % 1) * 60; - if (hours > 24) { - return timestamp.toDateString(); - } - if (hours > 1) { - return Math.floor(hours).toString() + ' hr ' + Math.floor(minutes) + ' min ago'; - } - if (minutes >= 2) { - return Math.floor(minutes).toString() + ' min ago'; - } - return 'about a minute ago'; - } AddressBarDialog { id: addressBarDialog @@ -88,6 +77,7 @@ Window { ListModel { id: suggestions } ListView { + id: scroll width: (3 * cardWidth) + (2 * hifi.layout.spacing); height: cardHeight; spacing: hifi.layout.spacing; @@ -103,10 +93,14 @@ Window { width: cardWidth; height: cardHeight; goFunction: goCard; - path: model.place_name + model.path; + userName: model.username; + placeName: model.place_name; + hifiUrl: model.place_name + model.path; + imageUrl: model.thumbnail_url; // This is wrong, but it will have to wait. thumbnail: model.thumbnail_url; - placeText: model.created_at ? "" : model.place_name; - usersText: model.created_at ? pastTime(model.created_at) : (model.online_users + ((model.online_users === 1) ? ' person' : ' people')); + action: model.action; + timestamp: model.created_at; + onlineUsers: model.online_users; hoverThunk: function () { ListView.view.currentIndex = index; } unhoverThunk: function () { ListView.view.currentIndex = -1; } } @@ -209,8 +203,24 @@ Window { } } } + + UserStoryCard { + id: storyCard; + visible: false; + visitPlace: function (hifiUrl) { + storyCard.visible = false; + addressLine.text = hifiUrl; + toggleOrGo(true); + }; + anchors { + verticalCenter: scroll.verticalCenter; + horizontalCenter: scroll.horizontalCenter; + verticalCenterOffset: 50; + } + } } + function toggleFeed () { useFeed = !useFeed; placesButton.buttonState = useFeed ? 0 : 1; @@ -318,13 +328,15 @@ Window { description = data.description || ""; return { place_name: name, + username: data.username || "", path: data.path || "", created_at: data.created_at || "", + action: data.action || "", thumbnail_url: data.thumbnail_url || "", tags: tags, description: description, - online_users: data.online_users, + online_users: data.online_users || 0, searchText: [name].concat(tags, description).join(' ').toUpperCase() } @@ -402,7 +414,6 @@ Window { {created_at: "8/3/2016", action: "snapshot", path: "/10077.4,4003.6,9972.56/0,-0.410351,0,0.911928", place_name: "Ventura", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/1f5/e6b/00-/thumbnail/hifi-place-1f5e6b00-2bf0-4319-b9ae-a2344a72354c.png?1454321596"} ]; } - var stories = data.user_stories.map(function (story) { // explicit single-argument function return makeModelData(story); }); diff --git a/interface/resources/qml/controls-uit/Button.qml b/interface/resources/qml/controls-uit/Button.qml index 298943b551..59f8a63238 100644 --- a/interface/resources/qml/controls-uit/Button.qml +++ b/interface/resources/qml/controls-uit/Button.qml @@ -21,6 +21,8 @@ Original.Button { width: 120 height: hifi.dimensions.controlLineHeight + HifiConstants { id: hifi } + style: ButtonStyle { background: Rectangle { diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index 5fae628283..278f9330d3 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -17,17 +17,54 @@ import QtGraphicalEffects 1.0 import "../styles-uit" Rectangle { + property string userName: ""; + property string placeName: ""; + property string action: ""; + property string timestamp: ""; + property string hifiUrl: ""; + property string thumbnail: defaultThumbnail; + property string imageUrl: ""; property var goFunction: null; - property alias image: lobby; - property alias placeText: place.text; - property alias usersText: users.text; + + property string timePhrase: pastTime(timestamp); + property string actionPhrase: makeActionPhrase(action); + property int onlineUsers: 0; + property bool isUserStory: userName && !onlineUsers; + property int textPadding: 20; property int textSize: 24; property int textSizeSmall: 18; property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif"); - property string thumbnail: defaultThumbnail; - property string path: ""; HifiConstants { id: hifi } + function pastTime(timestamp) { // Answer a descriptive string + timestamp = new Date(timestamp); + var then = timestamp.getTime(), + now = Date.now(), + since = now - then, + ONE_MINUTE = 1000 * 60, + ONE_HOUR = ONE_MINUTE * 60, + hours = since / ONE_HOUR, + minutes = (hours % 1) * 60; + if (hours > 24) { + return timestamp.toDateString(); + } + if (hours > 1) { + return Math.floor(hours).toString() + ' hr ' + Math.floor(minutes) + ' min ago'; + } + if (minutes >= 2) { + return Math.floor(minutes).toString() + ' min ago'; + } + return 'about a minute ago'; + } + function makeActionPhrase(actionLabel) { + switch (actionLabel) { + case "snapshot": + return "took a snapshot"; + default: + return "unknown" + } + } + Image { id: lobby; width: parent.width; @@ -39,7 +76,7 @@ Rectangle { anchors.left: parent.left; onStatusChanged: { if (status == Image.Error) { - console.log("source: " + source + ": failed to load " + path); + console.log("source: " + source + ": failed to load " + hfiUrl); source = defaultThumbnail; } } @@ -71,6 +108,7 @@ Rectangle { } RalewaySemiBold { id: place; + text: isUserStory ? "" : placeName; color: hifi.colors.white; size: textSize; anchors { @@ -81,6 +119,7 @@ Rectangle { } RalewayRegular { id: users; + text: isUserStory ? timePhrase : (onlineUsers + ((onlineUsers === 1) ? ' person' : ' people')); size: textSizeSmall; color: hifi.colors.white; anchors { diff --git a/interface/resources/qml/hifi/UserStoryCard.qml b/interface/resources/qml/hifi/UserStoryCard.qml new file mode 100644 index 0000000000..4b6c37dae8 --- /dev/null +++ b/interface/resources/qml/hifi/UserStoryCard.qml @@ -0,0 +1,83 @@ +// +// UserStoryCard.qml +// qml/hifi +// +// Displays a clickable card representing a user story or destination. +// +// Created by Howard Stearns on 8/11/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 +import QtQuick 2.5 +import "../styles-uit" as HifiStyles +import "../controls-uit" as HifiControls + +Rectangle { + id: storyCard; + width: 500; + height: 330; + property string userName: "User"; + property string placeName: "Home"; + property string actionPhrase: "did something"; + property string timePhrase: ""; + property string hifiUrl: storyCard.placeName; + property string imageUrl: Qt.resolvedUrl("../images/default-domain.gif"); + property var visitPlace: function (ignore) { }; + color: "white"; + HifiStyles.HifiConstants { id: otherHifi } + MouseArea { + anchors.fill: parent; + acceptedButtons: Qt.LeftButton; + onClicked: storyCard.visible = false; + hoverEnabled: true; + // The content of the storyCard has buttons. For these to work without being + // blanketed by the MouseArea, they need to be children of the MouseArea. + Image { + id: storyImage; + source: storyCard.imageUrl; + width: storyCard.width - 100; + height: storyImage.width / 1.91; + fillMode: Image.PreserveAspectCrop; + anchors { + horizontalCenter: parent.horizontalCenter; + top: parent.top; + topMargin: 20; + } + } + HifiStyles.RalewayRegular { + id: storyLabel; + text: storyCard.userName + " " + storyCard.actionPhrase + " in " + storyCard.placeName + size: 20; + color: "black" + anchors { + horizontalCenter: storyImage.horizontalCenter; + top: storyImage.bottom; + topMargin: hifi.layout.spacing + } + } + HifiStyles.RalewayRegular { + text: storyCard.timePhrase; + size: 15; + color: "slategrey" + anchors { + verticalCenter: visitButton.verticalCenter; + left: storyImage.left; + } + } + HifiControls.Button { + id: visitButton; + text: "visit " + storyCard.placeName; + color: otherHifi.buttons.blue; + onClicked: visitPlace(storyCard.hifiUrl); + anchors { + top: storyLabel.bottom; + topMargin: hifi.layout.spacing; + right: storyImage.right; + } + } + } +} From cd9bd8dddfed767b57d7042085fb2cad45d4b658 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 11 Aug 2016 16:58:06 -0700 Subject: [PATCH 061/134] we don't need the dummy data any more --- interface/resources/qml/AddressBarDialog.qml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index a65a228cf8..9e1eb37dea 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -407,13 +407,6 @@ Window { if (handleError(url, error, data, cb)) { return; } - // FIXME: For debugging until we have real data - if (!data.user_stories.length) { - data.user_stories = [ - {created_at: "8/3/2016", action: "snapshot", path: "/4257.1,126.084,1335.45/0,-0.857368,0,0.514705", place_name: "SpiritMoving", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/c28/a26/f0-/thumbnail/hifi-place-c28a26f0-6991-4654-9c2b-e64228c06954.jpg?1456878797"}, - {created_at: "8/3/2016", action: "snapshot", path: "/10077.4,4003.6,9972.56/0,-0.410351,0,0.911928", place_name: "Ventura", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/1f5/e6b/00-/thumbnail/hifi-place-1f5e6b00-2bf0-4319-b9ae-a2344a72354c.png?1454321596"} - ]; - } var stories = data.user_stories.map(function (story) { // explicit single-argument function return makeModelData(story); }); From b4a43db025f25ea58e634aeb6b7a52e458f66972 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 11 Aug 2016 17:04:48 -0700 Subject: [PATCH 062/134] include user name in search text for user stories --- interface/resources/qml/AddressBarDialog.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 9e1eb37dea..12fe44dcd8 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -324,7 +324,7 @@ Window { // ListModel elements will only ever have those properties that are defined by the first obj that is added. // So here we make sure that we have all the properties we need, regardless of whether it is a place data or user story. var name = optionalPlaceName || data.place_name, - tags = data.tags || [data.action], + tags = data.tags || [data.action, data.username], description = data.description || ""; return { place_name: name, @@ -338,7 +338,7 @@ Window { description: description, online_users: data.online_users || 0, - searchText: [name].concat(tags, description).join(' ').toUpperCase() + searchText: [name].concat(tags, description || []).join(' ').toUpperCase() } } function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData) From 8708e2ac2bd45e28708c9668e68946402083c5be Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 12 Aug 2016 07:00:07 -0700 Subject: [PATCH 063/134] image url, in anticipation of having it in details --- interface/resources/qml/AddressBarDialog.qml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 12fe44dcd8..988f13a0a7 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -48,7 +48,7 @@ Window { function goCard(card) { if (useFeed) { - storyCard.imageUrl = card.imageUrl; //"http://howard-stearns.github.io/models/images/dancing-avatars.jpg"; + storyCard.imageUrl = card.imageUrl; storyCard.userName = card.userName; storyCard.placeName = card.placeName; storyCard.actionPhrase = card.actionPhrase; @@ -96,7 +96,7 @@ Window { userName: model.username; placeName: model.place_name; hifiUrl: model.place_name + model.path; - imageUrl: model.thumbnail_url; // This is wrong, but it will have to wait. + imageUrl: model.image_url; thumbnail: model.thumbnail_url; action: model.action; timestamp: model.created_at; @@ -325,14 +325,24 @@ Window { // So here we make sure that we have all the properties we need, regardless of whether it is a place data or user story. var name = optionalPlaceName || data.place_name, tags = data.tags || [data.action, data.username], - description = data.description || ""; + description = data.description || "", + thumbnail_url = data.thumbnail_url || "", + image_url = thumbnail_url; + if (data.details) { + try { + image_url = JSON.parse(data.details).image_url || thumbnail_url; + } catch (e) { + console.log(name, "has bad details", data.details); + } + } return { place_name: name, username: data.username || "", path: data.path || "", created_at: data.created_at || "", action: data.action || "", - thumbnail_url: data.thumbnail_url || "", + thumbnail_url: thumbnail_url, + image_url: image_url, tags: tags, description: description, From 3408ad6f545e24ec35a289d8303d1bccc93121dc Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 12 Aug 2016 10:23:33 -0700 Subject: [PATCH 064/134] Wording change --- scripts/system/html/ShareSnapshot.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/ShareSnapshot.html index c054a3389a..00f805728c 100644 --- a/scripts/system/html/ShareSnapshot.html +++ b/scripts/system/html/ShareSnapshot.html @@ -71,12 +71,12 @@ if (!shareMsg.canShare) { // this means you may or may not be logged in, but can't share // because you are not in a public place. - document.getElementById("sharing").innerHTML = "

You can share if you are in a public place"; + document.getElementById("sharing").innerHTML = "

Snapshots can be shared when they're taken in shareable places."; } else if (!shareMsg.isLoggedIn) { // this means you are in a public place, but can't share because // you need to login. Soon we will just bring up the share dialog // in this case (and maybe set a boolean here to inform the html) - document.getElementById("sharing").innerHTML = "

You can share if you are logged in"; + document.getElementById("sharing").innerHTML = "

Snapshots can be shared when you are logged in."; } } window.onload = function () { From df0ceb17e83e5b5eec980fc30e830d0416f19b1f Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 12 Aug 2016 11:09:22 -0700 Subject: [PATCH 065/134] send (hi res image) details as a json string --- interface/src/ui/Snapshot.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index beb86af1c4..b7cdb1a126 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -197,7 +197,8 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { QJsonObject userStoryObject; QJsonObject detailsObject; detailsObject.insert("image_url", imageUrl); - userStoryObject.insert("details", detailsObject); + QString pickledDetails = QJsonDocument(detailsObject).toJson(); + userStoryObject.insert("details", pickledDetails); userStoryObject.insert("thumbnail_url", thumbnailUrl); userStoryObject.insert("place_name", placeName); userStoryObject.insert("path", currentPath); From ae9af88db287df65ad6d61cb24b2d29d84b996f8 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 12 Aug 2016 11:28:35 -0700 Subject: [PATCH 066/134] Spacing and better size for HMD pictures. --- scripts/system/html/ShareSnapshot.html | 8 +++++--- scripts/system/snapshot.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/ShareSnapshot.html index 00f805728c..a30532bbc9 100644 --- a/scripts/system/html/ShareSnapshot.html +++ b/scripts/system/html/ShareSnapshot.html @@ -35,11 +35,13 @@ } .snapsection{ - width:95% !important; - padding-right:0px; + width:95% !important; + padding-right:0px; + } + div#sharing { + margin-top:50px; } - div.clear { clear: both; } diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 4c0ba37ab3..39bcc7fe90 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -21,7 +21,7 @@ var button = toolBar.addButton({ }); function confirmShare(data) { - var dialog = new OverlayWebWindow('Snapshot', Script.resolvePath("html/ShareSnapshot.html"), 800, 300); + var dialog = new OverlayWebWindow('Snapshot', Script.resolvePath("html/ShareSnapshot.html"), 800, 470); function onMessage(message) { if (message == 'ready') { // The window can now receive data from us. dialog.emitScriptEvent(data); // Send it. From 1b62332058079cd0779657de3a12316b8b92688c Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 12 Aug 2016 11:50:11 -0700 Subject: [PATCH 067/134] don't show checkboxes on confirmation dialog when there's only one picture --- scripts/system/html/ShareSnapshot.html | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/ShareSnapshot.html index a30532bbc9..f9cc959ba9 100644 --- a/scripts/system/html/ShareSnapshot.html +++ b/scripts/system/html/ShareSnapshot.html @@ -46,7 +46,7 @@ @@ -120,16 +134,23 @@

-
-
- -
-
- -
-
- +
+
+
Would you like to share your pic in the Snapshots feed?
+
+
+
+
+ +
+
+
+ + + + +
diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 795e469c83..6c9132194e 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -20,24 +20,39 @@ var button = toolBar.addButton({ alpha: 0.9, }); +function showFeedWindow() { + DialogsManager.showFeed(); +} + +var openFeed, outstanding; function confirmShare(data) { - var dialog = new OverlayWebWindow('Snapshot', Script.resolvePath("html/ShareSnapshot.html"), 800, 470); + var dialog = new OverlayWebWindow('Snapshot Review', Script.resolvePath("html/ShareSnapshot.html"), 800, 470); function onMessage(message) { - if (message == 'ready') { // The window can now receive data from us. + switch (message) { + case 'ready': dialog.emitScriptEvent(data); // Send it. - return; - } // Rest is confirmation processing - dialog.webEventReceived.disconnect(onMessage); // I'm not certain that this is necessary. If it is, what do we do on normal close? - dialog.close(); - dialog.deleteLater(); - message = message.filter(function (picture) { return picture.share; }); - if (message.length) { - print('sharing', message.map(function (picture) { return picture.localPath; }).join(', ')); - message.forEach(function (data) { - Window.shareSnapshot(data.localPath); + openFeed = false; + outstanding = 0; + break; + case 'openSettings': + Desktop.show("hifi/dialogs/GeneralPreferencesDialog.qml", "GeneralPreferencesDialog"); + break; + default: + dialog.webEventReceived.disconnect(onMessage); // I'm not certain that this is necessary. If it is, what do we do on normal close? + dialog.close(); + dialog.deleteLater(); + message.forEach(function (submessage) { + if (submessage.share) { + print('sharing', submessage.localPath); + outstanding++; + Window.shareSnapshot(submessage.localPath); + } else if (submessage.openFeed) { + openFeed = true; + } }); - } else { - print('declined to share', JSON.stringify(data)); + if (openFeed && !outstanding) { + showFeedWindow(); + } } } dialog.webEventReceived.connect(onMessage); @@ -51,7 +66,10 @@ function snapshotShared(success) { } else { // for now just print an error. print('snapshot upload/share failed'); - } + } + if ((--outstanding <= 0) && openFeed) { + showFeedWindow(); + } } function onClicked() { From 5d19267d00e7237e6a5717d33b193a27acb60510 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Wed, 17 Aug 2016 11:10:38 -0700 Subject: [PATCH 080/134] Safeguard against file corruption This is what could be a temporary (or permanent) fix to users trying to delete important files on their computer through JS --- .../src/FileScriptingInterface.cpp | 19 +++++++++++++++++++ .../src/FileScriptingInterface.h | 1 + 2 files changed, 20 insertions(+) diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 63849c238d..2c8a68258f 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -39,6 +39,11 @@ void FileScriptingInterface::runUnzip(QString path, QUrl url) { QString tempDir = path; tempDir.remove(fileName); qDebug() << "Temporary directory at: " + tempDir; + if (!isTempDir(tempDir)) { + qDebug() << "Temporary directory mismatch; risk of losing files"; + return; + } + QString file = unzipFile(path, tempDir); if (file != "") { qDebug() << "file to upload: " + file; @@ -52,6 +57,20 @@ void FileScriptingInterface::runUnzip(QString path, QUrl url) { QDir(tempDir).removeRecursively(); } +// fix to check that we are only referring to a temporary directory +bool FileScriptingInterface::isTempDir(QString tempDir) { + QString folderName = "/" + tempDir.section("/", -1); + QString tempContainer = tempDir; + tempContainer.remove(folderName); + QTemporaryDir test; + QString testDir = test.path(); + folderName = "/" + testDir.section("/", -1); + QString testContainer = testDir; + testContainer.remove(folderName); + if (testContainer == tempContainer) return true; + return false; +} + bool FileScriptingInterface::isZippedFbx(QUrl url) { if (url.toString().contains(".zip") && url.toString().contains("fbx")) return true; qDebug() << "This model is not a .fbx packaged in a .zip. Please try with another model."; diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 2e8de6b174..dd6ca3225b 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -33,6 +33,7 @@ signals: void unzipSuccess(QString url); private: + bool isTempDir(QString tempDir); QString unzipFile(QString path, QString tempDir); void recursiveFileScan(QFileInfo file, QString* dirName); void downloadZip(QString path, const QString link); From e75f950ac70587a93471ae1fb0402a7b7d54acca Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 17 Aug 2016 14:12:40 -0700 Subject: [PATCH 081/134] Signal receivedHifiSchemeURL --- interface/src/Application.cpp | 1 + interface/src/Application.h | 1 + interface/src/ui/AddressBarDialog.cpp | 1 + interface/src/ui/AddressBarDialog.h | 1 + 4 files changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4077fc0d57..340597f18a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4853,6 +4853,7 @@ bool Application::canAcceptURL(const QString& urlString) const { bool Application::acceptURL(const QString& urlString, bool defaultUpload) { if (urlString.startsWith(HIFI_URL_SCHEME)) { // this is a hifi URL - have the AddressManager handle it + emit receivedHifiSchemeURL(urlString); QMetaObject::invokeMethod(DependencyManager::get().data(), "handleLookupString", Qt::AutoConnection, Q_ARG(const QString&, urlString)); return true; diff --git a/interface/src/Application.h b/interface/src/Application.h index 713febeb83..9fcce66f55 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -266,6 +266,7 @@ signals: void activeDisplayPluginChanged(); void uploadRequest(QString path); + void receivedHifiSchemeURL(QString path); public slots: QVector pasteEntities(float x, float y, float z); diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index e5b4262770..3e84c4c3c5 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -39,6 +39,7 @@ AddressBarDialog::AddressBarDialog(QQuickItem* parent) : OffscreenQmlDialog(pare _backEnabled = !(DependencyManager::get()->getBackStack().isEmpty()); _forwardEnabled = !(DependencyManager::get()->getForwardStack().isEmpty()); connect(DependencyManager::get().data(), &DialogsManager::setUseFeed, this, &AddressBarDialog::setUseFeed); + connect(qApp, &Application::receivedHifiSchemeURL, this, &AddressBarDialog::receivedHifiSchemeURL); } void AddressBarDialog::loadAddress(const QString& address, bool fromSuggestions) { diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index 10f0e0822a..68a12d4eb0 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -33,6 +33,7 @@ signals: void backEnabledChanged(); void forwardEnabledChanged(); void useFeedChanged(); + void receivedHifiSchemeURL(QString url); protected: void displayAddressOfflineMessage(); From d58cc8ddd99814557ed608c809c97c1c613c1335 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 17 Aug 2016 14:15:27 -0700 Subject: [PATCH 082/134] use html card from user_story id, and close things when receiveHifiSchemeUrl --- interface/resources/qml/AddressBarDialog.qml | 34 +- interface/resources/qml/AddressBarDialog.qml~ | 510 ++++++++++++++++++ interface/resources/qml/hifi/Card.qml | 1 + 3 files changed, 541 insertions(+), 4 deletions(-) create mode 100644 interface/resources/qml/AddressBarDialog.qml~ diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 832ba14013..7c2ef17590 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -15,6 +15,7 @@ import "styles" import "windows" import "hifi" import "hifi/toolbars" +import "controls-uit" as HifiControls Window { id: root @@ -46,15 +47,21 @@ Window { anchors.centerIn = parent; } + function resetAfterTeleport() { + console.log('hrs fixme got reset') + storyCardFrame.shown = root.shown = false; + } function goCard(card) { if (addressBarDialog.useFeed) { - storyCard.imageUrl = card.imageUrl; + /*storyCard.imageUrl = card.imageUrl; // hrs fixme storyCard.userName = card.userName; storyCard.placeName = card.placeName; storyCard.actionPhrase = card.actionPhrase; storyCard.timePhrase = card.timePhrase; storyCard.hifiUrl = card.hifiUrl; - storyCard.visible = true; + storyCard.visible = true;*/ + storyCard.url = metaverseBase + "user_stories/" + card.storyId + ".html"; + storyCardFrame.shown = true; return; } addressLine.text = card.hifiUrl; @@ -74,6 +81,7 @@ Window { onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0; onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0; onUseFeedChanged: { updateFeedState(); } + onReceivedHifiSchemeURL: { console.log('hrs status change'); console.log('hrs status got', url); resetAfterTeleport(); } ListModel { id: suggestions } @@ -102,6 +110,7 @@ Window { action: model.action; timestamp: model.created_at; onlineUsers: model.online_users; + storyId: model.metaverseId; hoverThunk: function () { ListView.view.currentIndex = index; } unhoverThunk: function () { ListView.view.currentIndex = -1; } } @@ -114,6 +123,7 @@ Window { Image { // Just a visual indicator that the user can swipe the cards over to see more. source: "../images/Swipe-Icon-single.svg" width: 50; + visible: suggestions.count > 3; anchors { right: scroll.right; verticalCenter: scroll.verticalCenter; @@ -214,14 +224,27 @@ Window { } } - UserStoryCard { + /*UserStoryCard { // hrs fixme remove id: storyCard; visible: false; visitPlace: function (hifiUrl) { storyCard.visible = false; addressLine.text = hifiUrl; toggleOrGo(true); - }; + };*/ + Window { + width: 750; + height: 360; + HifiControls.WebView { + anchors.fill: parent; + id: storyCard; + } + id: storyCardFrame; + + shown: false; + destroyOnCloseButton: false; + pinnable: false; + anchors { verticalCenter: scroll.verticalCenter; horizontalCenter: scroll.horizontalCenter; @@ -348,6 +371,7 @@ Window { console.log(name, "has bad details", data.details); } } + console.log('hrs fixme id', data.id, typeof data.id, JSON.stringify(data)); return { place_name: name, username: data.username || "", @@ -357,6 +381,8 @@ Window { thumbnail_url: thumbnail_url, image_url: image_url, + metaverseId: (data.id || "").toString(), // Some are strings from server while others are numbers. Model objects require uniformity. + tags: tags, description: description, online_users: data.online_users || 0, diff --git a/interface/resources/qml/AddressBarDialog.qml~ b/interface/resources/qml/AddressBarDialog.qml~ new file mode 100644 index 0000000000..5da49a1ee1 --- /dev/null +++ b/interface/resources/qml/AddressBarDialog.qml~ @@ -0,0 +1,510 @@ +// +// AddressBarDialog.qml +// +// Created by Austin Davis on 2015/04/14 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 +import QtQuick 2.4 +import "controls" +import "styles" +import "windows" +import "hifi" +import "hifi/toolbars" + +Window { + id: root + HifiConstants { id: hifi } + + objectName: "AddressBarDialog" + frame: HiddenFrame {} + hideBackground: true + + shown: false + destroyOnHidden: false + resizable: false + scale: 1.25 // Make this dialog a little larger than normal + + width: addressBarDialog.implicitWidth + height: addressBarDialog.implicitHeight + + onShownChanged: addressBarDialog.observeShownChanged(shown); + Component.onCompleted: { + root.parentChanged.connect(center); + center(); + } + Component.onDestruction: { + root.parentChanged.disconnect(center); + } + + function center() { + // Explicitly center in order to avoid warnings at shutdown + anchors.centerIn = parent; + } + + function goCard(card) { + if (addressBarDialog.useFeed) { + storyCard.imageUrl = card.imageUrl; + storyCard.userName = card.userName; + storyCard.placeName = card.placeName; + storyCard.actionPhrase = card.actionPhrase; + storyCard.timePhrase = card.timePhrase; + storyCard.hifiUrl = card.hifiUrl; + storyCard.visible = true; + return; + } + addressLine.text = card.hifiUrl; + toggleOrGo(true); + } + property var allPlaces: []; + property var allStories: []; + property int cardWidth: 200; + property int cardHeight: 152; + //property string metaverseBase: "https://metaverse.highfidelity.com/api/v1/"; + property string metaverseBase: "http://10.0.0.242:3000/api/v1/"; + + AddressBarDialog { + id: addressBarDialog + implicitWidth: backgroundImage.width + implicitHeight: backgroundImage.height + // The buttons have their button state changed on hover, so we have to manually fix them up here + onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0; + onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0; + onUseFeedChanged: { updateFeedState(); } + + ListModel { id: suggestions } + + ListView { + id: scroll + width: backgroundImage.width; + height: cardHeight; + spacing: hifi.layout.spacing; + clip: true; + anchors { + bottom: backgroundImage.top; + bottomMargin: 2 * hifi.layout.spacing; + horizontalCenter: backgroundImage.horizontalCenter + } + model: suggestions; + orientation: ListView.Horizontal; + delegate: Card { + width: cardWidth; + height: cardHeight; + goFunction: goCard; + userName: model.username; + placeName: model.place_name; + hifiUrl: model.place_name + model.path; + imageUrl: model.image_url; + thumbnail: model.thumbnail_url; + action: model.action; + timestamp: model.created_at; + onlineUsers: model.online_users; + hoverThunk: function () { ListView.view.currentIndex = index; } + unhoverThunk: function () { ListView.view.currentIndex = -1; } + } + highlightMoveDuration: -1; + highlightMoveVelocity: -1; + highlight: Rectangle { color: "transparent"; border.width: 4; border.color: "#1DB5ED"; z: 1; } + leftMargin: 50; // Start the first item over be about the same amount as the last item peeks through on the other side. + rightMargin: 50; + } + Image { // Just a visual indicator that the user can swipe the cards over to see more. + source: "../images/Swipe-Icon-single.svg" + width: 50; + anchors { + right: scroll.right; + verticalCenter: scroll.verticalCenter; + } + } + Image { + id: backgroundImage + source: "../images/address-bar.svg" + width: 576 * root.scale + height: 80 * root.scale + property int inputAreaHeight: 56.0 * root.scale // Height of the background's input area + property int inputAreaStep: (height - inputAreaHeight) / 2 + + ToolbarButton { + id: homeButton + imageURL: "../images/home.svg" + buttonState: 1 + defaultState: 1 + hoverState: 2 + onClicked: addressBarDialog.loadHome(); + anchors { + left: parent.left + leftMargin: homeButton.width / 2 + verticalCenter: parent.verticalCenter + } + } + + ToolbarButton { + id: backArrow; + imageURL: "../images/backward.svg"; + hoverState: addressBarDialog.backEnabled ? 2 : 0; + defaultState: addressBarDialog.backEnabled ? 1 : 0; + buttonState: addressBarDialog.backEnabled ? 1 : 0; + onClicked: addressBarDialog.loadBack(); + anchors { + left: homeButton.right + verticalCenter: parent.verticalCenter + } + } + ToolbarButton { + id: forwardArrow; + imageURL: "../images/forward.svg"; + hoverState: addressBarDialog.forwardEnabled ? 2 : 0; + defaultState: addressBarDialog.forwardEnabled ? 1 : 0; + buttonState: addressBarDialog.forwardEnabled ? 1 : 0; + onClicked: addressBarDialog.loadForward(); + anchors { + left: backArrow.right + verticalCenter: parent.verticalCenter + } + } + + // FIXME replace with TextField + TextInput { + id: addressLine + focus: true + anchors { + top: parent.top + bottom: parent.bottom + left: forwardArrow.right + right: placesButton.left + leftMargin: forwardArrow.width + rightMargin: placesButton.width + topMargin: parent.inputAreaStep + hifi.layout.spacing + bottomMargin: parent.inputAreaStep + hifi.layout.spacing + } + font.pixelSize: hifi.fonts.pixelSize * root.scale * 0.75 + helperText: "Go to: place, @user, /path, network address" + helperPixelSize: font.pixelSize * 0.75 + helperItalic: true + onTextChanged: filterChoicesByText() + } + // These two are radio buttons. + ToolbarButton { + id: placesButton + imageURL: "../images/places.svg" + buttonState: 1 + defaultState: addressBarDialog.useFeed ? 0 : 1; + hoverState: addressBarDialog.useFeed ? 2 : -1; + onClicked: addressBarDialog.useFeed ? toggleFeed() : identity() + anchors { + right: feedButton.left; + bottom: addressLine.bottom; + } + } + ToolbarButton { + id: feedButton; + imageURL: "../images/snap-feed.svg"; + buttonState: 0 + defaultState: addressBarDialog.useFeed ? 1 : 0; + hoverState: addressBarDialog.useFeed ? -1 : 2; + onClicked: addressBarDialog.useFeed ? identity() : toggleFeed(); + anchors { + right: parent.right; + bottom: addressLine.bottom; + rightMargin: feedButton.width / 2 + } + } + } + + UserStoryCard { + id: storyCard; + visible: false; + visitPlace: function (hifiUrl) { + storyCard.visible = false; + addressLine.text = hifiUrl; + toggleOrGo(true); + }; + anchors { + verticalCenter: scroll.verticalCenter; + horizontalCenter: scroll.horizontalCenter; + verticalCenterOffset: 50; + } + } + } + + + function toggleFeed() { + addressBarDialog.useFeed = !addressBarDialog.useFeed; + updateFeedState(); + } + function updateFeedState() { + placesButton.buttonState = addressBarDialog.useFeed ? 0 : 1; + feedButton.buttonState = addressBarDialog.useFeed ? 1 : 0; + filterChoicesByText(); + } + function getRequest(url, cb) { // cb(error, responseOfCorrectContentType) of url. General for 'get' text/html/json, but without redirects. + // TODO: make available to other .qml. + var request = new XMLHttpRequest(); + // QT bug: apparently doesn't handle onload. Workaround using readyState. + request.onreadystatechange = function () { + var READY_STATE_DONE = 4; + var HTTP_OK = 200; + if (request.readyState >= READY_STATE_DONE) { + var error = (request.status !== HTTP_OK) && request.status.toString() + ':' + request.statusText, + response = !error && request.responseText, + contentType = !error && request.getResponseHeader('content-type'); + if (!error && contentType.indexOf('application/json') === 0) { + try { + response = JSON.parse(response); + } catch (e) { + error = e; + } + } + cb(error, response); + } + }; + request.open("GET", url, true); + request.send(); + } + function asyncMap(array, iterator, cb) { + // call iterator(element, icb) once for each element of array, and then cb(error, mappedResult) + // when icb(error, mappedElement) has been called by each iterator. + // Calls to iterator are overlapped and map call icb in any order, but the mappedResults are collected in the same + // order as the elements of the array. + // short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.) + var count = array.length, results = []; + if (!count) { + return cb(null, results); + } + array.forEach(function (element, index) { + if (count < 0) { // don't keep iterating after we short-circuit + return; + } + iterator(element, function (error, mapped) { + results[index] = mapped; + if (error || !--count) { + count = 1; // don't cb multiple times if error + cb(error, results); + } + }); + }); + } + // Example: + /*asyncMap([0, 1, 2, 3, 4, 5, 6], function (elt, icb) { + console.log('called', elt); + setTimeout(function () { + console.log('answering', elt); + icb(null, elt); + }, Math.random() * 1000); + }, console.log); */ + + function identity(x) { + return x; + } + + function handleError(url, error, data, cb) { // cb(error) and answer truthy if needed, else falsey + if (!error && (data.status === 'success')) { + return; + } + if (!error) { // Create a message from the data + error = data.status + ': ' + data.error; + } + if (typeof(error) === 'string') { // Make a proper Error object + error = new Error(error); + } + error.message += ' in ' + url; // Include the url. + cb(error); + return true; + } + + function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description + var url = metaverseBase + 'places/' + placeData.place_name; + getRequest(url, function (error, data) { + if (handleError(url, error, data, cb)) { + return; + } + var place = data.data.place, previews = place.previews; + placeData.path = place.path; + if (previews && previews.thumbnail) { + placeData.thumbnail_url = previews.thumbnail; + } + if (place.description) { + placeData.description = place.description; + placeData.searchText += ' ' + place.description.toUpperCase(); + } + cb(error, placeData); + }); + } + function makeModelData(data, optionalPlaceName) { // create a new obj from data + // ListModel elements will only ever have those properties that are defined by the first obj that is added. + // So here we make sure that we have all the properties we need, regardless of whether it is a place data or user story. + var name = optionalPlaceName || data.place_name, + tags = data.tags || [data.action, data.username], + description = data.description || "", + thumbnail_url = data.thumbnail_url || "", + image_url = thumbnail_url; + if (data.details) { + try { + image_url = JSON.parse(data.details).image_url || thumbnail_url; + } catch (e) { + console.log(name, "has bad details", data.details); + } + } + return { + place_name: name, + username: data.username || "", + path: data.path || "", + created_at: data.created_at || "", + action: data.action || "", + thumbnail_url: thumbnail_url, + image_url: image_url, + + tags: tags, + description: description, + online_users: data.online_users || 0, + + searchText: [name].concat(tags, description || []).join(' ').toUpperCase() + } + } + function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData) + function addPlace(name, icb) { + getPlace(makeModelData(domain, name), icb); + } + // IWBNI we could get these results in order with most-recent-entered first. + // In any case, we don't really need to preserve the domain.names order in the results. + asyncMap(domain.names || [], addPlace, cb); + } + + function suggestable(place) { + if (addressBarDialog.useFeed) { + return true; + } + return (place.place_name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain. + && place.thumbnail_url + && place.online_users // at least one present means it's actually online + && place.online_users <= 20; + } + function getDomainPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model + // Each page of results is processed completely before we start on the next page. + // For each page of domains, we process each domain in parallel, and for each domain, process each place name in parallel. + // This gives us minimum latency within the page, but we do preserve the order within the page by using asyncMap and + // only appending the collected results. + var params = [ + 'open', // published hours handle now + // FIXME: should determine if place is actually running + 'restriction=open', // Not by whitelist, etc. FIXME: If logged in, add hifi to the restriction options, in order to include places that require login. + // FIXME add maturity + 'protocol=' + encodeURIComponent(AddressManager.protocolVersion()), + 'sort_by=users', + 'sort_order=desc', + 'page=' + pageNumber + ]; + var url = metaverseBase + 'domains/all?' + params.join('&'); + getRequest(url, function (error, data) { + if (handleError(url, error, data, cb)) { + return; + } + asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) { + if (error) { + return cb(error); + } + // pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ] + pageResults.forEach(function (domainResults) { + allPlaces = allPlaces.concat(domainResults); + if (!addressLine.text && !addressBarDialog.useFeed) { // Don't add if the user is already filtering + domainResults.forEach(function (place) { + if (suggestable(place)) { + suggestions.append(place); + } + }); + } + }); + if (data.current_page < data.total_pages) { + return getDomainPage(pageNumber + 1, cb); + } + cb(); + }); + }); + } + function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model + var url = metaverseBase + 'user_stories?page=' + pageNumber; + getRequest(url, function (error, data) { + if (handleError(url, error, data, cb)) { + return; + } + var stories = data.user_stories.map(function (story) { // explicit single-argument function + return makeModelData(story); + }); + allStories = allStories.concat(stories); + if (!addressLine.text && addressBarDialog.useFeed) { // Don't add if the user is already filtering + stories.forEach(function (story) { + suggestions.append(story); + }); + } + if ((data.current_page < data.total_pages) && (data.current_page <= 10)) { // just 10 pages = 100 stories for now + return getUserStoryPage(pageNumber + 1, cb); + } + cb(); + }); + } + function filterChoicesByText() { + suggestions.clear(); + var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity), + data = addressBarDialog.useFeed ? allStories : allPlaces; + function matches(place) { + if (!words.length) { + return suggestable(place); + } + return words.every(function (word) { + return place.searchText.indexOf(word) >= 0; + }); + } + data.forEach(function (place) { + if (matches(place)) { + suggestions.append(place); + } + }); + } + + function fillDestinations() { + allPlaces = []; + allStories = []; + suggestions.clear(); + getDomainPage(1, function (error) { + console.log('domain query', error || 'ok', allPlaces.length); + }); + getUserStoryPage(1, function (error) { + console.log('user stories query', error || 'ok', allStories.length); + }); + } + + onVisibleChanged: { + if (visible) { + addressLine.forceActiveFocus() + fillDestinations(); + } else { + addressLine.text = "" + } + } + + function toggleOrGo(fromSuggestions) { + if (addressLine.text !== "") { + addressBarDialog.loadAddress(addressLine.text, fromSuggestions) + } + root.shown = false; + } + + Keys.onPressed: { + switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + root.shown = false + event.accepted = true + break + case Qt.Key_Enter: + case Qt.Key_Return: + toggleOrGo() + event.accepted = true + break + } + } +} diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index 278f9330d3..fe162349c1 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -25,6 +25,7 @@ Rectangle { property string thumbnail: defaultThumbnail; property string imageUrl: ""; property var goFunction: null; + property string storyId: ""; property string timePhrase: pastTime(timestamp); property string actionPhrase: makeActionPhrase(action); From 0f415abd6b36fa279ce26137e3f901fec611787f Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 17 Aug 2016 16:56:52 -0700 Subject: [PATCH 083/134] dual purpose address bar - switchable between html and qml --- interface/resources/qml/AddressBarDialog.qml | 43 +- interface/resources/qml/AddressBarDialog.qml~ | 510 ------------------ 2 files changed, 26 insertions(+), 527 deletions(-) delete mode 100644 interface/resources/qml/AddressBarDialog.qml~ diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 7c2ef17590..089bec07f4 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -48,20 +48,22 @@ Window { } function resetAfterTeleport() { - console.log('hrs fixme got reset') storyCardFrame.shown = root.shown = false; } function goCard(card) { if (addressBarDialog.useFeed) { - /*storyCard.imageUrl = card.imageUrl; // hrs fixme - storyCard.userName = card.userName; - storyCard.placeName = card.placeName; - storyCard.actionPhrase = card.actionPhrase; - storyCard.timePhrase = card.timePhrase; - storyCard.hifiUrl = card.hifiUrl; - storyCard.visible = true;*/ - storyCard.url = metaverseBase + "user_stories/" + card.storyId + ".html"; - storyCardFrame.shown = true; + if (useHTML) { + storyCardHTML.url = metaverseBase + "user_stories/" + card.storyId + ".html"; + storyCardFrame.shown = true; + } else { + storyCardQML.imageUrl = card.imageUrl; + storyCardQML.userName = card.userName; + storyCardQML.placeName = card.placeName; + storyCardQML.actionPhrase = card.actionPhrase; + storyCardQML.timePhrase = card.timePhrase; + storyCardQML.hifiUrl = card.hifiUrl; + storyCardQML.visible = true; + } return; } addressLine.text = card.hifiUrl; @@ -72,6 +74,8 @@ Window { property int cardWidth: 200; property int cardHeight: 152; property string metaverseBase: "https://metaverse.highfidelity.com/api/v1/"; + //property string metaverseBase: "http://10.0.0.241:3000/api/v1/"; + property bool useHTML: false; // fixme: remove this and all false branches after the server is updated AddressBarDialog { id: addressBarDialog @@ -81,7 +85,7 @@ Window { onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0; onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0; onUseFeedChanged: { updateFeedState(); } - onReceivedHifiSchemeURL: { console.log('hrs status change'); console.log('hrs status got', url); resetAfterTeleport(); } + onReceivedHifiSchemeURL: resetAfterTeleport(); ListModel { id: suggestions } @@ -224,20 +228,26 @@ Window { } } - /*UserStoryCard { // hrs fixme remove - id: storyCard; + UserStoryCard { + id: storyCardQML; visible: false; visitPlace: function (hifiUrl) { - storyCard.visible = false; + storyCardQML.visible = false; addressLine.text = hifiUrl; toggleOrGo(true); - };*/ + }; + anchors { + verticalCenter: scroll.verticalCenter; + horizontalCenter: scroll.horizontalCenter; + verticalCenterOffset: 50; + } + } Window { width: 750; height: 360; HifiControls.WebView { anchors.fill: parent; - id: storyCard; + id: storyCardHTML; } id: storyCardFrame; @@ -371,7 +381,6 @@ Window { console.log(name, "has bad details", data.details); } } - console.log('hrs fixme id', data.id, typeof data.id, JSON.stringify(data)); return { place_name: name, username: data.username || "", diff --git a/interface/resources/qml/AddressBarDialog.qml~ b/interface/resources/qml/AddressBarDialog.qml~ deleted file mode 100644 index 5da49a1ee1..0000000000 --- a/interface/resources/qml/AddressBarDialog.qml~ +++ /dev/null @@ -1,510 +0,0 @@ -// -// AddressBarDialog.qml -// -// Created by Austin Davis on 2015/04/14 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import Hifi 1.0 -import QtQuick 2.4 -import "controls" -import "styles" -import "windows" -import "hifi" -import "hifi/toolbars" - -Window { - id: root - HifiConstants { id: hifi } - - objectName: "AddressBarDialog" - frame: HiddenFrame {} - hideBackground: true - - shown: false - destroyOnHidden: false - resizable: false - scale: 1.25 // Make this dialog a little larger than normal - - width: addressBarDialog.implicitWidth - height: addressBarDialog.implicitHeight - - onShownChanged: addressBarDialog.observeShownChanged(shown); - Component.onCompleted: { - root.parentChanged.connect(center); - center(); - } - Component.onDestruction: { - root.parentChanged.disconnect(center); - } - - function center() { - // Explicitly center in order to avoid warnings at shutdown - anchors.centerIn = parent; - } - - function goCard(card) { - if (addressBarDialog.useFeed) { - storyCard.imageUrl = card.imageUrl; - storyCard.userName = card.userName; - storyCard.placeName = card.placeName; - storyCard.actionPhrase = card.actionPhrase; - storyCard.timePhrase = card.timePhrase; - storyCard.hifiUrl = card.hifiUrl; - storyCard.visible = true; - return; - } - addressLine.text = card.hifiUrl; - toggleOrGo(true); - } - property var allPlaces: []; - property var allStories: []; - property int cardWidth: 200; - property int cardHeight: 152; - //property string metaverseBase: "https://metaverse.highfidelity.com/api/v1/"; - property string metaverseBase: "http://10.0.0.242:3000/api/v1/"; - - AddressBarDialog { - id: addressBarDialog - implicitWidth: backgroundImage.width - implicitHeight: backgroundImage.height - // The buttons have their button state changed on hover, so we have to manually fix them up here - onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0; - onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0; - onUseFeedChanged: { updateFeedState(); } - - ListModel { id: suggestions } - - ListView { - id: scroll - width: backgroundImage.width; - height: cardHeight; - spacing: hifi.layout.spacing; - clip: true; - anchors { - bottom: backgroundImage.top; - bottomMargin: 2 * hifi.layout.spacing; - horizontalCenter: backgroundImage.horizontalCenter - } - model: suggestions; - orientation: ListView.Horizontal; - delegate: Card { - width: cardWidth; - height: cardHeight; - goFunction: goCard; - userName: model.username; - placeName: model.place_name; - hifiUrl: model.place_name + model.path; - imageUrl: model.image_url; - thumbnail: model.thumbnail_url; - action: model.action; - timestamp: model.created_at; - onlineUsers: model.online_users; - hoverThunk: function () { ListView.view.currentIndex = index; } - unhoverThunk: function () { ListView.view.currentIndex = -1; } - } - highlightMoveDuration: -1; - highlightMoveVelocity: -1; - highlight: Rectangle { color: "transparent"; border.width: 4; border.color: "#1DB5ED"; z: 1; } - leftMargin: 50; // Start the first item over be about the same amount as the last item peeks through on the other side. - rightMargin: 50; - } - Image { // Just a visual indicator that the user can swipe the cards over to see more. - source: "../images/Swipe-Icon-single.svg" - width: 50; - anchors { - right: scroll.right; - verticalCenter: scroll.verticalCenter; - } - } - Image { - id: backgroundImage - source: "../images/address-bar.svg" - width: 576 * root.scale - height: 80 * root.scale - property int inputAreaHeight: 56.0 * root.scale // Height of the background's input area - property int inputAreaStep: (height - inputAreaHeight) / 2 - - ToolbarButton { - id: homeButton - imageURL: "../images/home.svg" - buttonState: 1 - defaultState: 1 - hoverState: 2 - onClicked: addressBarDialog.loadHome(); - anchors { - left: parent.left - leftMargin: homeButton.width / 2 - verticalCenter: parent.verticalCenter - } - } - - ToolbarButton { - id: backArrow; - imageURL: "../images/backward.svg"; - hoverState: addressBarDialog.backEnabled ? 2 : 0; - defaultState: addressBarDialog.backEnabled ? 1 : 0; - buttonState: addressBarDialog.backEnabled ? 1 : 0; - onClicked: addressBarDialog.loadBack(); - anchors { - left: homeButton.right - verticalCenter: parent.verticalCenter - } - } - ToolbarButton { - id: forwardArrow; - imageURL: "../images/forward.svg"; - hoverState: addressBarDialog.forwardEnabled ? 2 : 0; - defaultState: addressBarDialog.forwardEnabled ? 1 : 0; - buttonState: addressBarDialog.forwardEnabled ? 1 : 0; - onClicked: addressBarDialog.loadForward(); - anchors { - left: backArrow.right - verticalCenter: parent.verticalCenter - } - } - - // FIXME replace with TextField - TextInput { - id: addressLine - focus: true - anchors { - top: parent.top - bottom: parent.bottom - left: forwardArrow.right - right: placesButton.left - leftMargin: forwardArrow.width - rightMargin: placesButton.width - topMargin: parent.inputAreaStep + hifi.layout.spacing - bottomMargin: parent.inputAreaStep + hifi.layout.spacing - } - font.pixelSize: hifi.fonts.pixelSize * root.scale * 0.75 - helperText: "Go to: place, @user, /path, network address" - helperPixelSize: font.pixelSize * 0.75 - helperItalic: true - onTextChanged: filterChoicesByText() - } - // These two are radio buttons. - ToolbarButton { - id: placesButton - imageURL: "../images/places.svg" - buttonState: 1 - defaultState: addressBarDialog.useFeed ? 0 : 1; - hoverState: addressBarDialog.useFeed ? 2 : -1; - onClicked: addressBarDialog.useFeed ? toggleFeed() : identity() - anchors { - right: feedButton.left; - bottom: addressLine.bottom; - } - } - ToolbarButton { - id: feedButton; - imageURL: "../images/snap-feed.svg"; - buttonState: 0 - defaultState: addressBarDialog.useFeed ? 1 : 0; - hoverState: addressBarDialog.useFeed ? -1 : 2; - onClicked: addressBarDialog.useFeed ? identity() : toggleFeed(); - anchors { - right: parent.right; - bottom: addressLine.bottom; - rightMargin: feedButton.width / 2 - } - } - } - - UserStoryCard { - id: storyCard; - visible: false; - visitPlace: function (hifiUrl) { - storyCard.visible = false; - addressLine.text = hifiUrl; - toggleOrGo(true); - }; - anchors { - verticalCenter: scroll.verticalCenter; - horizontalCenter: scroll.horizontalCenter; - verticalCenterOffset: 50; - } - } - } - - - function toggleFeed() { - addressBarDialog.useFeed = !addressBarDialog.useFeed; - updateFeedState(); - } - function updateFeedState() { - placesButton.buttonState = addressBarDialog.useFeed ? 0 : 1; - feedButton.buttonState = addressBarDialog.useFeed ? 1 : 0; - filterChoicesByText(); - } - function getRequest(url, cb) { // cb(error, responseOfCorrectContentType) of url. General for 'get' text/html/json, but without redirects. - // TODO: make available to other .qml. - var request = new XMLHttpRequest(); - // QT bug: apparently doesn't handle onload. Workaround using readyState. - request.onreadystatechange = function () { - var READY_STATE_DONE = 4; - var HTTP_OK = 200; - if (request.readyState >= READY_STATE_DONE) { - var error = (request.status !== HTTP_OK) && request.status.toString() + ':' + request.statusText, - response = !error && request.responseText, - contentType = !error && request.getResponseHeader('content-type'); - if (!error && contentType.indexOf('application/json') === 0) { - try { - response = JSON.parse(response); - } catch (e) { - error = e; - } - } - cb(error, response); - } - }; - request.open("GET", url, true); - request.send(); - } - function asyncMap(array, iterator, cb) { - // call iterator(element, icb) once for each element of array, and then cb(error, mappedResult) - // when icb(error, mappedElement) has been called by each iterator. - // Calls to iterator are overlapped and map call icb in any order, but the mappedResults are collected in the same - // order as the elements of the array. - // short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.) - var count = array.length, results = []; - if (!count) { - return cb(null, results); - } - array.forEach(function (element, index) { - if (count < 0) { // don't keep iterating after we short-circuit - return; - } - iterator(element, function (error, mapped) { - results[index] = mapped; - if (error || !--count) { - count = 1; // don't cb multiple times if error - cb(error, results); - } - }); - }); - } - // Example: - /*asyncMap([0, 1, 2, 3, 4, 5, 6], function (elt, icb) { - console.log('called', elt); - setTimeout(function () { - console.log('answering', elt); - icb(null, elt); - }, Math.random() * 1000); - }, console.log); */ - - function identity(x) { - return x; - } - - function handleError(url, error, data, cb) { // cb(error) and answer truthy if needed, else falsey - if (!error && (data.status === 'success')) { - return; - } - if (!error) { // Create a message from the data - error = data.status + ': ' + data.error; - } - if (typeof(error) === 'string') { // Make a proper Error object - error = new Error(error); - } - error.message += ' in ' + url; // Include the url. - cb(error); - return true; - } - - function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description - var url = metaverseBase + 'places/' + placeData.place_name; - getRequest(url, function (error, data) { - if (handleError(url, error, data, cb)) { - return; - } - var place = data.data.place, previews = place.previews; - placeData.path = place.path; - if (previews && previews.thumbnail) { - placeData.thumbnail_url = previews.thumbnail; - } - if (place.description) { - placeData.description = place.description; - placeData.searchText += ' ' + place.description.toUpperCase(); - } - cb(error, placeData); - }); - } - function makeModelData(data, optionalPlaceName) { // create a new obj from data - // ListModel elements will only ever have those properties that are defined by the first obj that is added. - // So here we make sure that we have all the properties we need, regardless of whether it is a place data or user story. - var name = optionalPlaceName || data.place_name, - tags = data.tags || [data.action, data.username], - description = data.description || "", - thumbnail_url = data.thumbnail_url || "", - image_url = thumbnail_url; - if (data.details) { - try { - image_url = JSON.parse(data.details).image_url || thumbnail_url; - } catch (e) { - console.log(name, "has bad details", data.details); - } - } - return { - place_name: name, - username: data.username || "", - path: data.path || "", - created_at: data.created_at || "", - action: data.action || "", - thumbnail_url: thumbnail_url, - image_url: image_url, - - tags: tags, - description: description, - online_users: data.online_users || 0, - - searchText: [name].concat(tags, description || []).join(' ').toUpperCase() - } - } - function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData) - function addPlace(name, icb) { - getPlace(makeModelData(domain, name), icb); - } - // IWBNI we could get these results in order with most-recent-entered first. - // In any case, we don't really need to preserve the domain.names order in the results. - asyncMap(domain.names || [], addPlace, cb); - } - - function suggestable(place) { - if (addressBarDialog.useFeed) { - return true; - } - return (place.place_name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain. - && place.thumbnail_url - && place.online_users // at least one present means it's actually online - && place.online_users <= 20; - } - function getDomainPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model - // Each page of results is processed completely before we start on the next page. - // For each page of domains, we process each domain in parallel, and for each domain, process each place name in parallel. - // This gives us minimum latency within the page, but we do preserve the order within the page by using asyncMap and - // only appending the collected results. - var params = [ - 'open', // published hours handle now - // FIXME: should determine if place is actually running - 'restriction=open', // Not by whitelist, etc. FIXME: If logged in, add hifi to the restriction options, in order to include places that require login. - // FIXME add maturity - 'protocol=' + encodeURIComponent(AddressManager.protocolVersion()), - 'sort_by=users', - 'sort_order=desc', - 'page=' + pageNumber - ]; - var url = metaverseBase + 'domains/all?' + params.join('&'); - getRequest(url, function (error, data) { - if (handleError(url, error, data, cb)) { - return; - } - asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) { - if (error) { - return cb(error); - } - // pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ] - pageResults.forEach(function (domainResults) { - allPlaces = allPlaces.concat(domainResults); - if (!addressLine.text && !addressBarDialog.useFeed) { // Don't add if the user is already filtering - domainResults.forEach(function (place) { - if (suggestable(place)) { - suggestions.append(place); - } - }); - } - }); - if (data.current_page < data.total_pages) { - return getDomainPage(pageNumber + 1, cb); - } - cb(); - }); - }); - } - function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model - var url = metaverseBase + 'user_stories?page=' + pageNumber; - getRequest(url, function (error, data) { - if (handleError(url, error, data, cb)) { - return; - } - var stories = data.user_stories.map(function (story) { // explicit single-argument function - return makeModelData(story); - }); - allStories = allStories.concat(stories); - if (!addressLine.text && addressBarDialog.useFeed) { // Don't add if the user is already filtering - stories.forEach(function (story) { - suggestions.append(story); - }); - } - if ((data.current_page < data.total_pages) && (data.current_page <= 10)) { // just 10 pages = 100 stories for now - return getUserStoryPage(pageNumber + 1, cb); - } - cb(); - }); - } - function filterChoicesByText() { - suggestions.clear(); - var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity), - data = addressBarDialog.useFeed ? allStories : allPlaces; - function matches(place) { - if (!words.length) { - return suggestable(place); - } - return words.every(function (word) { - return place.searchText.indexOf(word) >= 0; - }); - } - data.forEach(function (place) { - if (matches(place)) { - suggestions.append(place); - } - }); - } - - function fillDestinations() { - allPlaces = []; - allStories = []; - suggestions.clear(); - getDomainPage(1, function (error) { - console.log('domain query', error || 'ok', allPlaces.length); - }); - getUserStoryPage(1, function (error) { - console.log('user stories query', error || 'ok', allStories.length); - }); - } - - onVisibleChanged: { - if (visible) { - addressLine.forceActiveFocus() - fillDestinations(); - } else { - addressLine.text = "" - } - } - - function toggleOrGo(fromSuggestions) { - if (addressLine.text !== "") { - addressBarDialog.loadAddress(addressLine.text, fromSuggestions) - } - root.shown = false; - } - - Keys.onPressed: { - switch (event.key) { - case Qt.Key_Escape: - case Qt.Key_Back: - root.shown = false - event.accepted = true - break - case Qt.Key_Enter: - case Qt.Key_Return: - toggleOrGo() - event.accepted = true - break - } - } -} From 5e8722ccf549a1f2b48c93d3dfc8d2c06787e773 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 18 Aug 2016 12:58:00 -0700 Subject: [PATCH 084/134] persist "open feed after" checkbox setting --- scripts/system/html/ShareSnapshot.html | 7 +++++-- scripts/system/snapshot.js | 27 ++++++++++++++++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/ShareSnapshot.html index 9098b30121..9b9403cf78 100644 --- a/scripts/system/html/ShareSnapshot.html +++ b/scripts/system/html/ShareSnapshot.html @@ -84,6 +84,9 @@ } function handleShareButtons(shareMsg) { + var openFeed = document.getElementById('openFeed'); + openFeed.checked = shareMsg.openFeedAfterShare; + openFeed.onchange = function () { EventBridge.emitWebEvent(openFeed.checked ? 'setOpenFeedTrue' : 'setOpenFeedFalse'); }; if (!shareMsg.canShare) { // this means you may or may not be logged in, but can't share // because you are not in a public place. @@ -116,10 +119,10 @@ }; // beware of bug: Cannot send objects at top level. (Nested in arrays is fine.) shareSelected = function () { - EventBridge.emitWebEvent(paths.concat({openFeed: document.getElementById("openFeed").checked})); + EventBridge.emitWebEvent(paths); }; doNotShare = function () { - EventBridge.emitWebEvent([{openFeed: document.getElementById("openFeed").checked}]); + EventBridge.emitWebEvent([]); }; snapshotSettings = function () { EventBridge.emitWebEvent("openSettings"); diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 6c9132194e..8e99783ff6 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -20,23 +20,32 @@ var button = toolBar.addButton({ alpha: 0.9, }); +function shouldOpenFeedAfterShare() { + var persisted = Settings.getValue('openFeedAfterShare', true); // might answer true, false, "true", or "false" + return persisted && (persisted !== 'false'); +} function showFeedWindow() { DialogsManager.showFeed(); } -var openFeed, outstanding; +var outstanding; function confirmShare(data) { var dialog = new OverlayWebWindow('Snapshot Review', Script.resolvePath("html/ShareSnapshot.html"), 800, 470); function onMessage(message) { switch (message) { case 'ready': dialog.emitScriptEvent(data); // Send it. - openFeed = false; outstanding = 0; break; case 'openSettings': Desktop.show("hifi/dialogs/GeneralPreferencesDialog.qml", "GeneralPreferencesDialog"); break; + case 'setOpenFeedFalse': + Settings.setValue('openFeedAfterShare', false) + break; + case 'setOpenFeedTrue': + Settings.setValue('openFeedAfterShare', true) + break; default: dialog.webEventReceived.disconnect(onMessage); // I'm not certain that this is necessary. If it is, what do we do on normal close? dialog.close(); @@ -46,11 +55,9 @@ function confirmShare(data) { print('sharing', submessage.localPath); outstanding++; Window.shareSnapshot(submessage.localPath); - } else if (submessage.openFeed) { - openFeed = true; } }); - if (openFeed && !outstanding) { + if (!outstanding && shouldOpenFeedAfterShare()) { showFeedWindow(); } } @@ -67,7 +74,7 @@ function snapshotShared(success) { // for now just print an error. print('snapshot upload/share failed'); } - if ((--outstanding <= 0) && openFeed) { + if ((--outstanding <= 0) && shouldOpenFeedAfterShare()) { showFeedWindow(); } } @@ -114,8 +121,12 @@ function resetButtons(path, notify) { // last element in data array tells dialog whether we can share or not confirmShare([ - { localPath: path }, - { canShare: Boolean(Window.location.placename), isLoggedIn: Account.isLoggedIn() } + { localPath: path }, + { + canShare: Boolean(Window.location.placename), + isLoggedIn: Account.isLoggedIn(), + openFeedAfterShare: shouldOpenFeedAfterShare() + } ]); } From 4492c4e64ecc83134c2cdbcac6a4e6bd8ed57eb3 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 18 Aug 2016 14:19:36 -0700 Subject: [PATCH 085/134] Allow javascript to safely open the correct login window (or answer that it is unneded). --- interface/src/scripting/AccountScriptingInterface.cpp | 5 +++++ interface/src/scripting/AccountScriptingInterface.h | 1 + 2 files changed, 6 insertions(+) diff --git a/interface/src/scripting/AccountScriptingInterface.cpp b/interface/src/scripting/AccountScriptingInterface.cpp index 4090c99ac8..d8533bb769 100644 --- a/interface/src/scripting/AccountScriptingInterface.cpp +++ b/interface/src/scripting/AccountScriptingInterface.cpp @@ -26,6 +26,11 @@ bool AccountScriptingInterface::isLoggedIn() { return accountManager->isLoggedIn(); } +bool AccountScriptingInterface::checkAndSignalForAccessToken() { + auto accountManager = DependencyManager::get(); + return accountManager->checkAndSignalForAccessToken(); +} + QString AccountScriptingInterface::getUsername() { auto accountManager = DependencyManager::get(); if (accountManager->isLoggedIn()) { diff --git a/interface/src/scripting/AccountScriptingInterface.h b/interface/src/scripting/AccountScriptingInterface.h index 49648781ce..0f958f2286 100644 --- a/interface/src/scripting/AccountScriptingInterface.h +++ b/interface/src/scripting/AccountScriptingInterface.h @@ -26,6 +26,7 @@ public slots: static AccountScriptingInterface* getInstance(); QString getUsername(); bool isLoggedIn(); + bool checkAndSignalForAccessToken(); }; #endif // hifi_AccountScriptingInterface_h From aab3b83ad9a138e3356a4851fa9758ec12d74562 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 18 Aug 2016 14:20:53 -0700 Subject: [PATCH 086/134] open login if user tries to share and is not logged in, rather than messaging user that they cannot share --- scripts/system/snapshot.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 8e99783ff6..92b16d31bc 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -32,6 +32,12 @@ var outstanding; function confirmShare(data) { var dialog = new OverlayWebWindow('Snapshot Review', Script.resolvePath("html/ShareSnapshot.html"), 800, 470); function onMessage(message) { + // Receives message from the html dialog via the qwebchannel EventBridge. This is complicated by the following: + // 1. Although we can send POJOs, we cannot receive a toplevel object. (Arrays of POJOs are fine, though.) + // 2. Although we currently use a single image, we would like to take snapshot, a selfie, a 360 etc. all at the + // same time, show the user all of them, and have the user deselect any that they do not want to share. + // So we'll ultimately be receiving a set of objects, perhaps with different post processing for each. + var isLoggedIn, needsLogin = false; switch (message) { case 'ready': dialog.emitScriptEvent(data); // Send it. @@ -50,16 +56,26 @@ function confirmShare(data) { dialog.webEventReceived.disconnect(onMessage); // I'm not certain that this is necessary. If it is, what do we do on normal close? dialog.close(); dialog.deleteLater(); + isLoggedIn = Account.isLoggedIn(); message.forEach(function (submessage) { + if (submessage.share && !isLoggedIn) { + needsLogin = true; + submessage.share = false; + } if (submessage.share) { print('sharing', submessage.localPath); outstanding++; Window.shareSnapshot(submessage.localPath); + } else { + print('not sharing', submessage.localPath); } }); if (!outstanding && shouldOpenFeedAfterShare()) { showFeedWindow(); } + if (needsLogin) { // after the possible feed, so that the login is on top + Account.checkAndSignalForAccessToken(); + } } } dialog.webEventReceived.connect(onMessage); @@ -124,7 +140,7 @@ function resetButtons(path, notify) { { localPath: path }, { canShare: Boolean(Window.location.placename), - isLoggedIn: Account.isLoggedIn(), + isLoggedIn: true, // Just have the dialog act as though we are. To be removed at both ends later. openFeedAfterShare: shouldOpenFeedAfterShare() } ]); From f6670a63746fcec41e9227b819a7519b4a2db16f Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 18 Aug 2016 16:29:42 -0700 Subject: [PATCH 087/134] new optional aspect-ratio argument to snapshot chain (javascript through c++ display plugin). When non-zero, it pulls out the largest piece from the center that maintains that ratio. Snapshot button uses 1.91. --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 +- .../src/scripting/WindowScriptingInterface.cpp | 6 +++--- .../src/scripting/WindowScriptingInterface.h | 2 +- .../src/display-plugins/NullDisplayPlugin.cpp | 2 +- .../src/display-plugins/NullDisplayPlugin.h | 2 +- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 17 ++++++++++++++--- .../src/display-plugins/OpenGLDisplayPlugin.h | 2 +- libraries/plugins/src/plugins/DisplayPlugin.h | 2 +- scripts/system/snapshot.js | 2 +- 10 files changed, 26 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 340597f18a..59ec1c0641 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5130,13 +5130,13 @@ void Application::toggleLogDialog() { } } -void Application::takeSnapshot(bool notify) { +void Application::takeSnapshot(bool notify, float aspectRatio) { QMediaPlayer* player = new QMediaPlayer(); QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); player->play(); - QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot()); + QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio)); emit DependencyManager::get()->snapshotTaken(path, notify); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 9fcce66f55..667969abf1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -250,7 +250,7 @@ public: float getAvatarSimrate() const { return _avatarSimCounter.rate(); } float getAverageSimsPerSecond() const { return _simCounter.rate(); } - void takeSnapshot(bool notify); + void takeSnapshot(bool notify, float aspectRatio = 0.0f); void shareSnapshot(const QString& filename); model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; } diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index f843673c07..f68f6d212a 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -204,10 +204,10 @@ void WindowScriptingInterface::copyToClipboard(const QString& text) { QApplication::clipboard()->setText(text); } -void WindowScriptingInterface::takeSnapshot(bool notify) { +void WindowScriptingInterface::takeSnapshot(bool notify, float aspectRatio) { // only evil-doers call takeSnapshot from a random thread - qApp->postLambdaEvent([notify] { - qApp->takeSnapshot(notify); + qApp->postLambdaEvent([notify, aspectRatio] { + qApp->takeSnapshot(notify, aspectRatio); }); } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 15dc1a8004..ca82753598 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -55,7 +55,7 @@ public slots: QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); void showAssetServer(const QString& upload = ""); void copyToClipboard(const QString& text); - void takeSnapshot(bool notify); + void takeSnapshot(bool notify = true, float aspectRatio = 0.0f); void shareSnapshot(const QString& path); signals: diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index 5ee05fa2e3..a4777b087b 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -31,6 +31,6 @@ void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) { } } -QImage NullDisplayPlugin::getScreenshot() const { +QImage NullDisplayPlugin::getScreenshot(float aspectRatio) const { return QImage(); } diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index 198c89ae78..1852ed53ee 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -18,7 +18,7 @@ public: glm::uvec2 getRecommendedRenderSize() const override; bool hasFocus() const override; void submitFrame(const gpu::FramePointer& newFrame) override; - QImage getScreenshot() const override; + QImage getScreenshot(float aspectRatio = 0.0f) const override; private: static const QString NAME; }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 905042cb79..7334191b75 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -659,15 +659,26 @@ void OpenGLDisplayPlugin::withMainThreadContext(std::function f) const { _container->makeRenderingContextCurrent(); } -QImage OpenGLDisplayPlugin::getScreenshot() const { +QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { auto size = _compositeFramebuffer->getSize(); if (isHmd()) { size.x /= 2; } + auto bestSize = size; + uvec2 corner(0); + if (aspectRatio != 0.0f) { // Pick out the largest piece of the center that produces the requested width/height aspectRatio + if (((size.y * aspectRatio) + 0.5f) < size.x) { + bestSize.x = round(size.y * aspectRatio); + } else { + bestSize.y = round(size.x / aspectRatio); + } + corner.x = round((size.x - bestSize.x) / 2.0f); + corner.y = round((size.y - bestSize.y) / 2.0f); + } auto glBackend = const_cast(*this).getGLBackend(); - QImage screenshot(size.x, size.y, QImage::Format_ARGB32); + QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32); withMainThreadContext([&] { - glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(uvec2(0), size), screenshot); + glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot); }); return screenshot.mirrored(false, true); } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 48f9a78eda..51b33c9bcd 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -54,7 +54,7 @@ public: return getSurfaceSize(); } - QImage getScreenshot() const override; + QImage getScreenshot(float aspectRatio = 0.0f) const override; float presentRate() const override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 49c341cdcb..288cee3223 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -172,7 +172,7 @@ public: } // Fetch the most recently displayed image as a QImage - virtual QImage getScreenshot() const = 0; + virtual QImage getScreenshot(float aspectRatio = 0.0f) const = 0; // will query the underlying hmd api to compute the most recent head pose virtual bool beginFrameRender(uint32_t frameIndex) { return true; } diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 92b16d31bc..5c893fad4a 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -116,7 +116,7 @@ function onClicked() { // take snapshot (with no notification) Script.setTimeout(function () { - Window.takeSnapshot(false); + Window.takeSnapshot(false, 1.91); }, SNAPSHOT_DELAY); } From 4d7d483c0eac43fca4232c6b4d44ff1601d9c372 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 19 Aug 2016 09:51:58 -0700 Subject: [PATCH 088/134] use ceil --- .../display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 7334191b75..b304b3802e 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -667,7 +667,7 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { auto bestSize = size; uvec2 corner(0); if (aspectRatio != 0.0f) { // Pick out the largest piece of the center that produces the requested width/height aspectRatio - if (((size.y * aspectRatio) + 0.5f) < size.x) { + if (ceil(size.y * aspectRatio) < size.x) { bestSize.x = round(size.y * aspectRatio); } else { bestSize.y = round(size.x / aspectRatio); From 8bc9a92429396763b36761b69bc5848e2c54053f Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Fri, 19 Aug 2016 11:32:13 -0700 Subject: [PATCH 089/134] removed extraneous debug prints --- interface/resources/qml/AssetServer.qml | 1 - interface/resources/qml/MarketplaceComboBox.qml | 2 -- interface/resources/qml/controls-uit/WebView.qml | 1 - interface/resources/qml/hifi/Desktop.qml | 7 ++----- libraries/script-engine/src/FileScriptingInterface.cpp | 7 +------ 5 files changed, 3 insertions(+), 15 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index 87dcf9368c..050bc8e99e 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -328,7 +328,6 @@ ScrollingWindow { id: timer } function uploadClicked(fileUrl) { - console.log("Upload clicked url: " + fileUrl); if (uploadOpen) { return; } diff --git a/interface/resources/qml/MarketplaceComboBox.qml b/interface/resources/qml/MarketplaceComboBox.qml index 559f4b9d65..7a600d7bbe 100644 --- a/interface/resources/qml/MarketplaceComboBox.qml +++ b/interface/resources/qml/MarketplaceComboBox.qml @@ -49,7 +49,6 @@ Rectangle { element.click();' onNewViewRequested: { - console.log("new view requested url"); var component = Qt.createComponent("Browser.qml"); var newWindow = component.createObject(desktop); request.openIn(newWindow.webView); @@ -68,7 +67,6 @@ Rectangle { onLinkHovered: { desktop.currentUrl = hoveredUrl - console.log("my url in WebView: " + desktop.currentUrl) if (File.isZippedFbx(desktop.currentUrl)) { runJavaScript(simpleDownload, function(){console.log("ran the JS");}); } diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index 8069ee79fb..faf7f746a2 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -51,7 +51,6 @@ WebEngineView { onLoadingChanged: { // Required to support clicking on "hifi://" links - console.log("loading change requested url"); if (WebEngineView.LoadStartedStatus == loadRequest.status) { var url = loadRequest.url.toString(); if (urlHandler.canHandleUrl(url)) { diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index ebc776617f..62f31f07fc 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -80,7 +80,7 @@ OriginalDesktop.Desktop { property string tempDir: "" function initWebviewProfileHandlers(profile) { - console.log("the webview url in desktop is: " + currentUrl); + console.log("The webview url in desktop is: " + currentUrl); if (webViewProfileSetup) return; webViewProfileSetup = true; @@ -90,9 +90,8 @@ OriginalDesktop.Desktop { tempDir = File.getTempDir(); console.log("Temp dir created: " + tempDir); download.path = tempDir + "/" + adaptedPath; - console.log("Path where it should download: " + download.path); + console.log("Path where object should download: " + download.path); download.accept(); - console.log("Download accept: " + download.state); if (download.state === WebEngineDownloadItem.DownloadInterrupted) { console.log("download failed to complete"); } @@ -100,8 +99,6 @@ OriginalDesktop.Desktop { profile.downloadFinished.connect(function(download){ if (download.state === WebEngineDownloadItem.DownloadCompleted) { - console.log("Download Finished: " + download.state); - console.log("File object is: " + File); File.runUnzip(download.path, currentUrl); } else { console.log("The download was corrupted, state: " + download.state); diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 2c8a68258f..fa38e46d31 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -35,7 +35,6 @@ void FileScriptingInterface::runUnzip(QString path, QUrl url) { qDebug() << "Url that was downloaded: " + url.toString(); qDebug() << "Path where download is saved: " + path; QString fileName = "/" + path.section("/", -1); - qDebug() << "Filename to remove from temp path: " + fileName; QString tempDir = path; tempDir.remove(fileName); qDebug() << "Temporary directory at: " + tempDir; @@ -46,9 +45,8 @@ void FileScriptingInterface::runUnzip(QString path, QUrl url) { QString file = unzipFile(path, tempDir); if (file != "") { - qDebug() << "file to upload: " + file; + qDebug() << "Object file to upload: " + file; QUrl url = QUrl::fromLocalFile(file); - qDebug() << "url from local file: " + url.toString(); emit unzipSuccess(url.toString()); } else { qDebug() << "unzip failed"; @@ -73,7 +71,6 @@ bool FileScriptingInterface::isTempDir(QString tempDir) { bool FileScriptingInterface::isZippedFbx(QUrl url) { if (url.toString().contains(".zip") && url.toString().contains("fbx")) return true; - qDebug() << "This model is not a .fbx packaged in a .zip. Please try with another model."; return false; } @@ -108,9 +105,7 @@ QString FileScriptingInterface::unzipFile(QString path, QString tempDir) { QDir dir(path); QString dirName = dir.path(); - qDebug() << "Zip directory is stored at: " + dirName; QString target = tempDir + "/model_repo"; - qDebug() << "Target path: " + target; QStringList list = JlCompress::extractDir(dirName, target); qDebug() << list; From a3d64dbd9c360d15fe53e706fde540db1ca83097 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 19 Aug 2016 14:14:31 -0700 Subject: [PATCH 090/134] code cleanup --- interface/resources/qml/AddressBarDialog.qml | 3 +-- interface/src/Application.h | 2 +- interface/src/scripting/WindowScriptingInterface.h | 2 +- interface/src/ui/AddressBarDialog.h | 5 ++++- interface/src/ui/Snapshot.cpp | 10 ++++------ .../html/{ShareSnapshot.html => SnapshotReview.html} | 0 scripts/system/snapshot.js | 10 ++++------ 7 files changed, 15 insertions(+), 17 deletions(-) rename scripts/system/html/{ShareSnapshot.html => SnapshotReview.html} (100%) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 089bec07f4..b61b4111d6 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -73,8 +73,7 @@ Window { property var allStories: []; property int cardWidth: 200; property int cardHeight: 152; - property string metaverseBase: "https://metaverse.highfidelity.com/api/v1/"; - //property string metaverseBase: "http://10.0.0.241:3000/api/v1/"; + property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/"; property bool useHTML: false; // fixme: remove this and all false branches after the server is updated AddressBarDialog { diff --git a/interface/src/Application.h b/interface/src/Application.h index 667969abf1..0ce1aac566 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -266,7 +266,7 @@ signals: void activeDisplayPluginChanged(); void uploadRequest(QString path); - void receivedHifiSchemeURL(QString path); + void receivedHifiSchemeURL(const QString& url); public slots: QVector pasteEntities(float x, float y, float z); diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index ca82753598..7a01be7fac 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -63,7 +63,7 @@ signals: void svoImportRequested(const QString& url); void domainConnectionRefused(const QString& reasonMessage, int reasonCode); void snapshotTaken(const QString& path, bool notify); - void snapshotShared(bool success); + void snapshotShared(const QString& error); private slots: WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height); diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index 68a12d4eb0..3197770433 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -14,6 +14,7 @@ #define hifi_AddressBarDialog_h #include +#include class AddressBarDialog : public OffscreenQmlDialog { Q_OBJECT @@ -21,6 +22,7 @@ class AddressBarDialog : public OffscreenQmlDialog { Q_PROPERTY(bool backEnabled READ backEnabled NOTIFY backEnabledChanged) Q_PROPERTY(bool forwardEnabled READ forwardEnabled NOTIFY forwardEnabledChanged) Q_PROPERTY(bool useFeed READ useFeed WRITE setUseFeed NOTIFY useFeedChanged) + Q_PROPERTY(QString metaverseServerUrl READ metaverseServerUrl) public: AddressBarDialog(QQuickItem* parent = nullptr); @@ -28,12 +30,13 @@ public: bool forwardEnabled() { return _forwardEnabled; } bool useFeed() { return _useFeed; } void setUseFeed(bool useFeed) { if (_useFeed != useFeed) { _useFeed = useFeed; emit useFeedChanged(); } } + QString metaverseServerUrl() { return NetworkingConstants::METAVERSE_SERVER_URL.toString(); } signals: void backEnabledChanged(); void forwardEnabledChanged(); void useFeedChanged(); - void receivedHifiSchemeURL(QString url); + void receivedHifiSchemeURL(const QString& url); protected: void displayAddressOfflineMessage(); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index b7cdb1a126..4513894f5a 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -215,20 +215,18 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { QJsonDocument(rootObject).toJson()); } else { - emit DependencyManager::get()->snapshotShared(false); + emit DependencyManager::get()->snapshotShared(contents); } } void SnapshotUploader::uploadFailure(QNetworkReply& reply) { - // TODO: parse response, potentially helpful for logging (?) - emit DependencyManager::get()->snapshotShared(false); + emit DependencyManager::get()->snapshotShared(reply.readAll()); } void SnapshotUploader::createStorySuccess(QNetworkReply& reply) { - emit DependencyManager::get()->snapshotShared(true); + emit DependencyManager::get()->snapshotShared(""); } void SnapshotUploader::createStoryFailure(QNetworkReply& reply) { - // TODO: parse response, potentially helpful for logging (?) - emit DependencyManager::get()->snapshotShared(false); + emit DependencyManager::get()->snapshotShared(reply.readAll()); } diff --git a/scripts/system/html/ShareSnapshot.html b/scripts/system/html/SnapshotReview.html similarity index 100% rename from scripts/system/html/ShareSnapshot.html rename to scripts/system/html/SnapshotReview.html diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 5c893fad4a..fab26a70e6 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -30,7 +30,7 @@ function showFeedWindow() { var outstanding; function confirmShare(data) { - var dialog = new OverlayWebWindow('Snapshot Review', Script.resolvePath("html/ShareSnapshot.html"), 800, 470); + var dialog = new OverlayWebWindow('Snapshot Review', Script.resolvePath("html/SnapshotReview.html"), 800, 470); function onMessage(message) { // Receives message from the html dialog via the qwebchannel EventBridge. This is complicated by the following: // 1. Although we can send POJOs, we cannot receive a toplevel object. (Arrays of POJOs are fine, though.) @@ -82,13 +82,11 @@ function confirmShare(data) { dialog.raise(); } -function snapshotShared(success) { - if (success) { - // for now just print status +function snapshotShared(errorMessage) { + if (!errorMessage) { print('snapshot uploaded and shared'); } else { - // for now just print an error. - print('snapshot upload/share failed'); + print(errorMessage); } if ((--outstanding <= 0) && shouldOpenFeedAfterShare()) { showFeedWindow(); From 1e08914f8d608e790dabcddabccc520bb705d143 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 19 Aug 2016 14:32:15 -0700 Subject: [PATCH 091/134] simplify --- scripts/system/snapshot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index fab26a70e6..9ce3cb366e 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -137,7 +137,7 @@ function resetButtons(path, notify) { confirmShare([ { localPath: path }, { - canShare: Boolean(Window.location.placename), + canShare: Boolean(location.placename), isLoggedIn: true, // Just have the dialog act as though we are. To be removed at both ends later. openFeedAfterShare: shouldOpenFeedAfterShare() } From 3d2afaac77df4addd18d559cdd503b036ec21c0a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 20 Aug 2016 11:19:30 +1200 Subject: [PATCH 092/134] Size and position snapshot dialog content blocks --- scripts/system/html/SnapshotReview.html | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/scripts/system/html/SnapshotReview.html b/scripts/system/html/SnapshotReview.html index 9b9403cf78..8d73e5295f 100644 --- a/scripts/system/html/SnapshotReview.html +++ b/scripts/system/html/SnapshotReview.html @@ -3,6 +3,41 @@ Share + - - + diff --git a/scripts/system/html/css/SnapshotReview.css b/scripts/system/html/css/SnapshotReview.css new file mode 100644 index 0000000000..4faa17e7a3 --- /dev/null +++ b/scripts/system/html/css/SnapshotReview.css @@ -0,0 +1,131 @@ +/* +// edit-style.css +// +// Created by Howard Stearns for David Rowe 8/22/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + + +.snapshot-container { + width: 100%; + padding-top: 3px; +} + +.snapshot-column-left { + width: 320px; + position: absolute; + padding-top: 8px; +} + +.snapshot-column-right { + margin-left: 342px; +} + +.snapshot-column-right > div > img { + width: 100%; +} + +@media (max-width: 768px) { + .snapshot-column-left { + position: initial; + width: 100%; + } + .snapshot-column-right { + margin-left: 0; + width: 100%; + } + .snapshot-column-right > div > img { + margin-top: 18px !important; + } +} + +.snapshot-column-right > div { + position: relative; + padding: 2px; +} + +.snapshot-column-right > div > img { + border: 2px solid #575757; + margin: -2px; +} + +hr { + padding-left: 0; + padding-right: 0; + margin: 21px 0; +} + +.snapsection { + text-align: center; +} + +.title { + text-transform: uppercase; + font-size: 12px; +} + +.prompt { + font-family: Raleway-SemiBold; + font-size: 14px; +} + +div.button { + padding-top: 21px; +} + +.compound-button { + position: relative; + height: auto; +} + +.compound-button input { + padding-left: 40px; +} + +.compound-button .glyph { + display: inline-block; + position: absolute; + left: 12px; + top: 16px; + width: 23px; + height: 23px; + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgaGVpZ2h0PSI0MCIKICAgd2lkdGg9IjQwIgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIKICAgdmlld0JveD0iMCAwIDQwIDQwIgogICB5PSIwcHgiCiAgIHg9IjBweCIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGEzNCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48ZGM6dGl0bGU+PC9kYzp0aXRsZT48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczMyIiAvPjxzdHlsZQogICAgIGlkPSJzdHlsZTQiCiAgICAgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOiM0MTQwNDI7fQoJLnN0MXtmaWxsOiNDQ0NDQ0M7fQoJLnN0MntmaWxsOiMxMzk4QkI7fQoJLnN0M3tmaWxsOiMzMUQ4RkY7fQo8L3N0eWxlPjxnCiAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMTEwKSIKICAgICBpZD0iTGF5ZXJfMSI+PGNpcmNsZQogICAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZjtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJjaXJjbGUxMyIKICAgICAgIHI9IjQuNDQwMDAwMSIKICAgICAgIGN5PSIxMjYuMTciCiAgICAgICBjeD0iMjAuNTQwMDAxIgogICAgICAgY2xhc3M9InN0MSIgLz48cGF0aAogICAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZjtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJwYXRoMTUiCiAgICAgICBkPSJtIDI4Ljg3LDEzOS4yNiBjIDAuMDEsLTAuMDEgMC4wMiwtMC4wMiAwLjAzLC0wLjAzIGwgMCwtMS44NiBjIDAsLTIuNjggLTIuMzMsLTQuNzcgLTUsLTQuNzcgbCAtNi40MiwwIGMgLTIuNjgsMCAtNC44NSwyLjA5IC00Ljg1LDQuNzcgbCAwLDEuODggMTYuMjQsMCB6IgogICAgICAgY2xhc3M9InN0MSIgLz48cGF0aAogICAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZjtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJwYXRoMTciCiAgICAgICBkPSJtIDM4LjE3LDEyMy40MiBjIDAsLTMuOTcgLTMuMjIsLTcuMTkgLTcuMTksLTcuMTkgbCAtMjAuMzEsMCBjIC0zLjk3LDAgLTcuMTksMy4yMiAtNy4xOSw3LjE5IGwgMCwxNC4xOCBjIDAsMy45NyAzLjIyLDcuMTkgNy4xOSw3LjE5IGwgMjAuMzEsMCBjIDMuOTcsMCA3LjE5LC0zLjIyIDcuMTksLTcuMTkgbCAwLC0xNC4xOCB6IG0gLTEuNzgsMTQuMjcgYyAwLDMuMDMgLTIuNDYsNS40OSAtNS40OSw1LjQ5IGwgLTIwLjMyLDAgYyAtMy4wMywwIC01LjQ5LC0yLjQ2IC01LjQ5LC01LjQ5IGwgMCwtMTQuMTkgYyAwLC0zLjAzIDIuNDYsLTUuNDkgNS40OSwtNS40OSBsIDIwLjMzLDAgYyAzLjAzLDAgNS40OSwyLjQ2IDUuNDksNS40OSBsIDAsMTQuMTkgeiIKICAgICAgIGNsYXNzPSJzdDEiIC8+PC9nPjxnCiAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMTEwKSIKICAgICBpZD0iTGF5ZXJfMiIgLz48L3N2Zz4=); + background-repeat: no-repeat; + background-size: 23px 23px; +} + +.setting { + display: inline-table; + height: 28px; +} + +.setting label { + display: table-cell; + vertical-align: middle; + font-family: Raleway-SemiBold; + font-size: 14px; +} + +.setting + .setting { + margin-left: 18px; +} + +input[type=button].naked { + font-size: 40px; + line-height: 40px; + width: 30px; + padding: 0; + margin: 0 0 -6px 0; + position: relative; + top: -6px; + left: -8px; + background: none; +} + +input[type=button].naked:hover { + color: #00b4ef; + background: none; +} diff --git a/scripts/system/html/js/SnapshotReview.js b/scripts/system/html/js/SnapshotReview.js new file mode 100644 index 0000000000..a6515df825 --- /dev/null +++ b/scripts/system/html/js/SnapshotReview.js @@ -0,0 +1,77 @@ +"use strict"; +// +// SnapshotReview.js +// scripts/system/html/js/ +// +// Created by Howard Stearns 8/22/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var paths = [], idCounter = 0, useCheckboxes; +function addImage(data) { + var div = document.createElement("DIV"), + input = document.createElement("INPUT"), + label = document.createElement("LABEL"), + img = document.createElement("IMG"), + id = "p" + idCounter++; + function toggle() { data.share = input.checked; } + img.src = data.localPath; + div.appendChild(img); + data.share = true; + if (useCheckboxes) { // I'd rather use css, but the included stylesheet is quite particular. + // Our stylesheet(?) requires input.id to match label.for. Otherwise input doesn't display the check state. + label.setAttribute('for', id); // cannot do label.for = + input.id = id; + input.type = "checkbox"; + input.checked = true; + input.addEventListener('change', toggle); + div.class = "property checkbox"; + div.appendChild(input); + div.appendChild(label); + } + document.getElementById("snapshot-images").appendChild(div); + paths.push(data); + +} +function handleShareButtons(shareMsg) { + var openFeed = document.getElementById('openFeed'); + openFeed.checked = shareMsg.openFeedAfterShare; + openFeed.onchange = function () { EventBridge.emitWebEvent(openFeed.checked ? 'setOpenFeedTrue' : 'setOpenFeedFalse'); }; + if (!shareMsg.canShare) { + // this means you may or may not be logged in, but can't share + // because you are not in a public place. + document.getElementById("sharing").innerHTML = "

Snapshots can be shared when they're taken in shareable places."; + } +} +window.onload = function () { + // Something like the following will allow testing in a browser. + //addImage({localPath: 'c:/Users/howar/OneDrive/Pictures/hifi-snap-by--on-2016-07-27_12-58-43.jpg'}); + //addImage({localPath: 'http://lorempixel.com/1512/1680'}); + openEventBridge(function () { + // Set up a handler for receiving the data, and tell the .js we are ready to receive it. + EventBridge.scriptEventReceived.connect(function (message) { + // last element of list contains a bool for whether or not we can share stuff + var shareMsg = message.pop(); + handleShareButtons(shareMsg); + + // rest are image paths which we add + useCheckboxes = message.length > 1; + message.forEach(addImage); + }); + EventBridge.emitWebEvent('ready'); + }); + +}; +// beware of bug: Cannot send objects at top level. (Nested in arrays is fine.) +function shareSelected() { + EventBridge.emitWebEvent(paths); +}; +function doNotShare() { + EventBridge.emitWebEvent([]); +}; +function snapshotSettings() { + EventBridge.emitWebEvent("openSettings"); +}; From 8bf87128d98e6cd5c7a0a27e798bbebff34fb8a8 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Mon, 22 Aug 2016 16:04:55 -0700 Subject: [PATCH 109/134] Fixed browser.qml 'onNewViewRequested' --- interface/resources/qml/Browser.qml | 5 +++++ interface/resources/qml/MarketplaceComboBox.qml | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 3693b9dfea..050e10eead 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -217,6 +217,11 @@ ScrollingWindow { } onIconChanged: { console.log("New icon: " + icon) + } + onNewViewRequested: { + var component = Qt.createComponent("Browser.qml"); + var newWindow = component.createObject(desktop); + request.openIn(newWindow.webView) } Component.onCompleted: { desktop.initWebviewProfileHandlers(webview.profile) diff --git a/interface/resources/qml/MarketplaceComboBox.qml b/interface/resources/qml/MarketplaceComboBox.qml index 7a600d7bbe..f7f224485b 100644 --- a/interface/resources/qml/MarketplaceComboBox.qml +++ b/interface/resources/qml/MarketplaceComboBox.qml @@ -66,7 +66,8 @@ Rectangle { element.removeAttr("download");' onLinkHovered: { - desktop.currentUrl = hoveredUrl + desktop.currentUrl = hoveredUrl; + // add an error message for non-fbx files if (File.isZippedFbx(desktop.currentUrl)) { runJavaScript(simpleDownload, function(){console.log("ran the JS");}); } From bc90b0bc43fc37be9d26cc755130fd429859dab7 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 22 Aug 2016 16:09:09 -0700 Subject: [PATCH 110/134] pr review --- interface/resources/qml/AddressBarDialog.qml | 12 ++++++------ interface/resources/qml/hifi/Card.qml | 6 +++++- scripts/system/html/css/SnapshotReview.css | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 7be7c2c83b..f2bdc5ba6d 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -273,9 +273,9 @@ Window { function asyncMap(array, iterator, cb) { // call iterator(element, icb) once for each element of array, and then cb(error, mappedResult) // when icb(error, mappedElement) has been called by each iterator. - // Calls to iterator are overlapped and map call icb in any order, but the mappedResults are collected in the same + // Calls to iterator are overlapped and may call icb in any order, but the mappedResults are collected in the same // order as the elements of the array. - // short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.) + // Short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.) var count = array.length, results = []; if (!count) { return cb(null, results); @@ -287,7 +287,7 @@ Window { iterator(element, function (error, mapped) { results[index] = mapped; if (error || !--count) { - count = 1; // don't cb multiple times if error + count = 0; // don't cb multiple times if error cb(error, results); } }); @@ -397,9 +397,9 @@ Window { // only appending the collected results. var params = [ 'open', // published hours handle now - // FIXME: should determine if place is actually running - 'restriction=open', // Not by whitelist, etc. FIXME: If logged in, add hifi to the restriction options, in order to include places that require login. - // FIXME add maturity + // TBD: should determine if place is actually running? + 'restriction=open', // Not by whitelist, etc. TBD: If logged in, add hifi to the restriction options, in order to include places that require login? + // TBD: add maturity? 'protocol=' + encodeURIComponent(AddressManager.protocolVersion()), 'sort_by=users', 'sort_order=desc', diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index fe162349c1..53829eed9e 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -37,6 +37,7 @@ Rectangle { property int textSizeSmall: 18; property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif"); HifiConstants { id: hifi } + function pastTime(timestamp) { // Answer a descriptive string timestamp = new Date(timestamp); var then = timestamp.getTime(), @@ -77,7 +78,7 @@ Rectangle { anchors.left: parent.left; onStatusChanged: { if (status == Image.Error) { - console.log("source: " + source + ": failed to load " + hfiUrl); + console.log("source: " + source + ": failed to load " + hifiUrl); source = defaultThumbnail; } } @@ -129,6 +130,9 @@ Rectangle { margins: textPadding; } } + // These two can be supplied to provide hover behavior. + // For example, AddressBarDialog provides functions that set the current list view item + // to that which is being hovered over. property var hoverThunk: function () { }; property var unhoverThunk: function () { }; MouseArea { diff --git a/scripts/system/html/css/SnapshotReview.css b/scripts/system/html/css/SnapshotReview.css index 4faa17e7a3..c2965f92e1 100644 --- a/scripts/system/html/css/SnapshotReview.css +++ b/scripts/system/html/css/SnapshotReview.css @@ -1,5 +1,5 @@ /* -// edit-style.css +// SnapshotReview.css // // Created by Howard Stearns for David Rowe 8/22/2016. // Copyright 2016 High Fidelity, Inc. From 4b61cc9f5fabb375cab2ff950fc6a87532a02471 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 22 Aug 2016 17:30:08 -0700 Subject: [PATCH 111/134] new user data editor --- scripts/system/html/css/edit-style.css | 18 +- .../system/html/css/img/jsoneditor-icons.svg | 893 +++++++++++++++++ scripts/system/html/css/jsoneditor.css | 934 ++++++++++++++++++ scripts/system/html/entityProperties.html | 15 +- scripts/system/html/js/entityProperties.js | 473 ++++++--- scripts/system/html/js/jsoneditor.min.js | 49 + 6 files changed, 2241 insertions(+), 141 deletions(-) create mode 100644 scripts/system/html/css/img/jsoneditor-icons.svg create mode 100644 scripts/system/html/css/jsoneditor.css create mode 100644 scripts/system/html/js/jsoneditor.min.js diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 0b58cf22ac..58f8833db3 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -798,7 +798,7 @@ tuple, .blue:focus, .tuple .z:focus, .tuple .roll:focus { } ::-webkit-scrollbar { - width: 10px; + width: 20px; height: 10px; } ::-webkit-scrollbar-track { @@ -1081,3 +1081,19 @@ input#reset-to-natural-dimensions { #animation-fps { margin-top: 48px; } + +#userdata-clear{ + margin-bottom: 10px; +} + + +#static-userdata{ + display: none; + z-index: 99; + position: absolute; + width: 96%; + padding-left:1%; + margin-top:5px; + margin-bottom:10px; + background-color: #2e2e2e; +} \ No newline at end of file diff --git a/scripts/system/html/css/img/jsoneditor-icons.svg b/scripts/system/html/css/img/jsoneditor-icons.svg new file mode 100644 index 0000000000..1b40068aad --- /dev/null +++ b/scripts/system/html/css/img/jsoneditor-icons.svg @@ -0,0 +1,893 @@ + + + JSON Editor Icons + + + + image/svg+xml + + JSON Editor Icons + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/html/css/jsoneditor.css b/scripts/system/html/css/jsoneditor.css new file mode 100644 index 0000000000..aea0696609 --- /dev/null +++ b/scripts/system/html/css/jsoneditor.css @@ -0,0 +1,934 @@ +/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */ + +div.jsoneditor input { + height: auto; + border: inherit; +} + +div.jsoneditor input:focus { + border: none !important; + box-shadow: none !important; +} + +div.jsoneditor table { + border-collapse: collapse; + width: auto; +} + +div.jsoneditor td, +div.jsoneditor th { + padding: 0; + display: table-cell; + text-align: left; + vertical-align: inherit; + border-radius: inherit; +} + + +div.jsoneditor-field, +div.jsoneditor-value, +div.jsoneditor-readonly { + border: 1px solid transparent; + min-height: 16px; + min-width: 32px; + padding: 2px; + margin: 1px; + word-wrap: break-word; + float: left; +} + +/* adjust margin of p elements inside editable divs, needed for Opera, IE */ + +div.jsoneditor-field p, +div.jsoneditor-value p { + margin: 0; +} + +div.jsoneditor-value { + word-break: break-word; +} + +div.jsoneditor-readonly { + min-width: 16px; + color: red; +} + +div.jsoneditor-empty { + border-color: lightgray; + border-style: dashed; + border-radius: 2px; +} + +div.jsoneditor-field.jsoneditor-empty::after, +div.jsoneditor-value.jsoneditor-empty::after { + pointer-events: none; + color: lightgray; + font-size: 8pt; +} + +div.jsoneditor-field.jsoneditor-empty::after { + content: "field"; +} + +div.jsoneditor-value.jsoneditor-empty::after { + content: "value"; +} + +div.jsoneditor-value.jsoneditor-url, +a.jsoneditor-value.jsoneditor-url { + color: green; + text-decoration: underline; +} + +a.jsoneditor-value.jsoneditor-url { + display: inline-block; + padding: 2px; + margin: 2px; +} + +a.jsoneditor-value.jsoneditor-url:hover, +a.jsoneditor-value.jsoneditor-url:focus { + color: #ee422e; +} + +div.jsoneditor td.jsoneditor-separator { + padding: 3px 0; + vertical-align: top; + color: gray; +} + +div.jsoneditor-field[contenteditable=true]:focus, +div.jsoneditor-field[contenteditable=true]:hover, +div.jsoneditor-value[contenteditable=true]:focus, +div.jsoneditor-value[contenteditable=true]:hover, +div.jsoneditor-field.jsoneditor-highlight, +div.jsoneditor-value.jsoneditor-highlight { + background-color: #FFFFAB; + border: 1px solid yellow; + border-radius: 2px; +} + +div.jsoneditor-field.jsoneditor-highlight-active, +div.jsoneditor-field.jsoneditor-highlight-active:focus, +div.jsoneditor-field.jsoneditor-highlight-active:hover, +div.jsoneditor-value.jsoneditor-highlight-active, +div.jsoneditor-value.jsoneditor-highlight-active:focus, +div.jsoneditor-value.jsoneditor-highlight-active:hover { + background-color: #ffee00; + border: 1px solid #ffc700; + border-radius: 2px; +} + +div.jsoneditor-value.jsoneditor-string { + color: #008000; +} + +div.jsoneditor-value.jsoneditor-object, +div.jsoneditor-value.jsoneditor-array { + min-width: 16px; + color: #808080; +} + +div.jsoneditor-value.jsoneditor-number { + color: #ee422e; +} + +div.jsoneditor-value.jsoneditor-boolean { + color: #ff8c00; +} + +div.jsoneditor-value.jsoneditor-null { + color: #004ED0; +} + +div.jsoneditor-value.jsoneditor-invalid { + color: #000000; +} + +div.jsoneditor-tree button { + width: 24px; + height: 24px; + padding: 0; + margin: 0; + border: none; + cursor: pointer; + background: transparent url("img/jsoneditor-icons.svg"); +} + +div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree, +div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree { + cursor: pointer; +} + +div.jsoneditor-tree button.jsoneditor-collapsed { + background-position: 0 -48px; +} + +div.jsoneditor-tree button.jsoneditor-expanded { + background-position: 0 -72px; +} + +div.jsoneditor-tree button.jsoneditor-contextmenu { + background-position: -48px -72px; +} + +div.jsoneditor-tree button.jsoneditor-contextmenu:hover, +div.jsoneditor-tree button.jsoneditor-contextmenu:focus, +div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { + background-position: -48px -48px; +} + +div.jsoneditor-tree *:focus { + outline: none; +} + +div.jsoneditor-tree button:focus { + /* TODO: nice outline for buttons with focus + outline: #97B0F8 solid 2px; + box-shadow: 0 0 8px #97B0F8; + */ + background-color: #f5f5f5; + outline: #e5e5e5 solid 1px; +} + +div.jsoneditor-tree button.jsoneditor-invisible { + visibility: hidden; + background: none; +} + +#userdata-editor{ + height:100%; +} + +div.jsoneditor { + color: #1A1A1A; + border: 1px solid #2e2e2e; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + overflow: hidden; + position: relative; + padding: 0; + line-height: 100%; + min-height: 200px; +} + +div.jsoneditor-tree table.jsoneditor-tree { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + margin: 0; +} + +div.jsoneditor-outer { + width: 100%; + height: 100%; + margin: -35px 0 0 0; + padding: 0 0 0 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + overflow-y: auto; +} + +textarea.jsoneditor-text, +.ace-jsoneditor { + min-height: 150px; +} + +div.jsoneditor-tree { + width: 100%; + height: 100%; + position: relative; +} + +textarea.jsoneditor-text { + width: 100%; + height: 100%; + margin: 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + outline-width: 0; + border: none; + background-color: white; + resize: none; +} + +tr.jsoneditor-highlight, +tr.jsoneditor-selected { + background-color: #e6e6e6; +} + +tr.jsoneditor-selected button.jsoneditor-dragarea, +tr.jsoneditor-selected button.jsoneditor-contextmenu { + visibility: hidden; +} + +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu { + visibility: visible; +} + +div.jsoneditor-tree button.jsoneditor-dragarea { + background: url("img/jsoneditor-icons.svg") -72px -72px; + cursor: move; +} + +div.jsoneditor-tree button.jsoneditor-dragarea:hover, +div.jsoneditor-tree button.jsoneditor-dragarea:focus, +tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea { + background-position: -72px -48px; +} + +div.jsoneditor tr, +div.jsoneditor th, +div.jsoneditor td { + padding: 0; + margin: 0; + overflow: visible; +} + +div.jsoneditor td { + vertical-align: top; +} + +div.jsoneditor td.jsoneditor-tree { + vertical-align: top; +} + +div.jsoneditor-field, +div.jsoneditor-value, +div.jsoneditor td, +div.jsoneditor th, +div.jsoneditor textarea, +.jsoneditor-schema-error { + font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; + font-size: 10pt; + color: grey; +} + +/* popover */ + +.jsoneditor-schema-error { + cursor: default; + display: inline-block; + /*font-family: arial, sans-serif;*/ + height: 24px; + line-height: 24px; + position: relative; + text-align: center; + width: 24px; +} + +div.jsoneditor-tree .jsoneditor-schema-error { + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.svg") -168px -48px; +} + +.jsoneditor-schema-error .jsoneditor-popover { + background-color: #4c4c4c; + border-radius: 3px; + box-shadow: 0 0 5px rgba(0,0,0,0.4); + color: #fff; + display: none; + padding: 7px 10px; + position: absolute; + width: 200px; + z-index: 4; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above { + bottom: 32px; + left: -98px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below { + top: 32px; + left: -98px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left { + top: -7px; + right: 32px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right { + top: -7px; + left: 32px; +} + +.jsoneditor-schema-error .jsoneditor-popover:before { + border-right: 7px solid transparent; + border-left: 7px solid transparent; + content: ''; + display: block; + left: 50%; + margin-left: -7px; + position: absolute; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before { + border-top: 7px solid #4c4c4c; + bottom: -7px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before { + border-bottom: 7px solid #4c4c4c; + top: -7px; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before { + border-left: 7px solid #4c4c4c; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + content: ''; + top: 19px; + right: -14px; + left: inherit; + margin-left: inherit; + margin-top: -7px; + position: absolute; +} + +.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before { + border-right: 7px solid #4c4c4c; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + content: ''; + top: 19px; + left: -14px; + margin-left: inherit; + margin-top: -7px; + position: absolute; +} + +.jsoneditor-schema-error:hover .jsoneditor-popover, +.jsoneditor-schema-error:focus .jsoneditor-popover { + display: block; + -webkit-animation: fade-in .3s linear 1, move-up .3s linear 1; + -moz-animation: fade-in .3s linear 1, move-up .3s linear 1; + -ms-animation: fade-in .3s linear 1, move-up .3s linear 1; +} + +@-webkit-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@-moz-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@-ms-keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +/*@-webkit-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/*@-moz-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/*@-ms-keyframes move-up {*/ + +/*from { bottom: 24px; }*/ + +/*to { bottom: 32px; }*/ + +/*}*/ + +/* JSON schema errors displayed at the bottom of the editor in mode text and code */ + +.jsoneditor .jsoneditor-text-errors { + width: 100%; + border-collapse: collapse; + background-color: #ffef8b; + border-top: 1px solid #ffd700; +} + +.jsoneditor .jsoneditor-text-errors td { + padding: 3px 6px; + vertical-align: middle; +} + +.jsoneditor-text-errors .jsoneditor-schema-error { + border: none; + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.svg") -168px -48px; +} +/* ContextMenu - main menu */ + +div.jsoneditor-contextmenu-root { + position: relative; + width: 0; + height: 0; +} + +div.jsoneditor-contextmenu { + position: absolute; + box-sizing: content-box; + z-index: 99999; +} + +div.jsoneditor-contextmenu ul, +div.jsoneditor-contextmenu li { + box-sizing: content-box; +} + +div.jsoneditor-contextmenu ul { + position: relative; + left: 0; + top: 0; + width: 124px; + background: white; + border: 1px solid #d3d3d3; + box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3); + list-style: none; + margin: 0; + padding: 0; +} + +div.jsoneditor-contextmenu ul li button { + padding: 0; + margin: 0; + width: 124px; + height: 24px; + border: none; + cursor: pointer; + color: #4d4d4d; + background: transparent; + font-size: 10pt; + font-family: arial, sans-serif; + box-sizing: border-box; + line-height: 26px; + text-align: left; +} + +/* Fix button padding in firefox */ + +div.jsoneditor-contextmenu ul li button::-moz-focus-inner { + padding: 0; + border: 0; +} + +div.jsoneditor-contextmenu ul li button:hover, +div.jsoneditor-contextmenu ul li button:focus { + color: #1a1a1a; + background-color: #f5f5f5; + outline: none; +} + +div.jsoneditor-contextmenu ul li button.jsoneditor-default { + width: 92px; +} + +div.jsoneditor-contextmenu ul li button.jsoneditor-expand { + float: right; + width: 32px; + height: 24px; + border-left: 1px solid #e5e5e5; +} + +div.jsoneditor-contextmenu div.jsoneditor-icon { + float: left; + width: 24px; + height: 24px; + border: none; + padding: 0; + margin: 0; + background-image: url("img/jsoneditor-icons.svg"); +} + +div.jsoneditor-contextmenu ul li button div.jsoneditor-expand { + float: right; + width: 24px; + height: 24px; + padding: 0; + margin: 0 4px 0 0; + background: url("img/jsoneditor-icons.svg") 0 -72px; + opacity: 0.4; +} + +div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand, +div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand { + opacity: 1; +} + +div.jsoneditor-contextmenu div.jsoneditor-separator { + height: 0; + border-top: 1px solid #e5e5e5; + padding-top: 5px; + margin-top: 5px; +} + +div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon { + background-position: -24px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon { + background-position: -24px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon { + background-position: 0 -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon { + background-position: 0 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon { + background-position: 0 -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon { + background-position: 0 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon { + background-position: -48px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon { + background-position: -48px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon { + background-position: -168px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon { + background-position: -168px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon { + background-position: -192px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon { + background-position: -192px 0; +} + +/* ContextMenu - sub menu */ + +div.jsoneditor-contextmenu ul li button.jsoneditor-selected, +div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover, +div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus { + color: white; + background-color: #ee422e; +} + +div.jsoneditor-contextmenu ul li { + overflow: hidden; +} + +div.jsoneditor-contextmenu ul li ul { + display: none; + position: relative; + left: -10px; + top: 0; + border: none; + box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5); + padding: 0 10px; + /* TODO: transition is not supported on IE8-9 */ + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} + + + +div.jsoneditor-contextmenu ul li ul li button { + padding-left: 24px; + animation: all ease-in-out 1s; +} + +div.jsoneditor-contextmenu ul li ul li button:hover, +div.jsoneditor-contextmenu ul li ul li button:focus { + background-color: #f5f5f5; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon { + background-position: -144px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon { + background-position: -144px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon { + background-position: -120px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon { + background-position: -120px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon { + background-position: -72px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon { + background-position: -72px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon { + background-position: -96px -24px; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon, +div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon { + background-position: -96px 0; +} + +div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon { + background-image: none; + width: 6px; +} +div.jsoneditor-menu { + width: 100%; + height: 35px; + padding: 2px; + margin: 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + color: white; + background-color: #2e2e2e; + border-bottom: 1px solid #2e2e2e; +} + +div.jsoneditor-menu > button, +div.jsoneditor-menu > div.jsoneditor-modes > button { + width: 26px; + height: 26px; + margin: 2px; + padding: 0; + border-radius: 2px; + border: 1px solid transparent; + background: transparent url("img/jsoneditor-icons.svg"); + color: white; + opacity: 0.8; + font-family: arial, sans-serif; + font-size: 10pt; + float: left; +} + +div.jsoneditor-menu > button:hover, +div.jsoneditor-menu > div.jsoneditor-modes > button:hover { + background-color: rgba(255,255,255,0.2); + border: 1px solid rgba(255,255,255,0.4); +} + +div.jsoneditor-menu > button:focus, +div.jsoneditor-menu > button:active, +div.jsoneditor-menu > div.jsoneditor-modes > button:focus, +div.jsoneditor-menu > div.jsoneditor-modes > button:active { + background-color: rgba(255,255,255,0.3); +} + +div.jsoneditor-menu > button:disabled, +div.jsoneditor-menu > div.jsoneditor-modes > button:disabled { + opacity: 0.5; +} + +div.jsoneditor-menu > button.jsoneditor-collapse-all { + background-position: 0 -96px; +} + +div.jsoneditor-menu > button.jsoneditor-expand-all { + background-position: 0 -120px; +} + +div.jsoneditor-menu > button.jsoneditor-undo { + background-position: -24px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-undo:disabled { + background-position: -24px -120px; +} + +div.jsoneditor-menu > button.jsoneditor-redo { + background-position: -48px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-redo:disabled { + background-position: -48px -120px; +} + +div.jsoneditor-menu > button.jsoneditor-compact { + background-position: -72px -96px; +} + +div.jsoneditor-menu > button.jsoneditor-format { + background-position: -72px -120px; +} + +div.jsoneditor-menu > div.jsoneditor-modes { + display: inline-block; + float: left; +} + +div.jsoneditor-menu > div.jsoneditor-modes > button { + background-image: none; + width: auto; + padding-left: 6px; + padding-right: 6px; +} + +div.jsoneditor-menu > button.jsoneditor-separator, +div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator { + margin-left: 10px; +} + +div.jsoneditor-menu a { + font-family: arial, sans-serif; + font-size: 10pt; + color: white; + opacity: 0.8; + vertical-align: middle; +} + +div.jsoneditor-menu a:hover { + opacity: 1; +} + +div.jsoneditor-menu a.jsoneditor-poweredBy { + font-size: 8pt; + position: absolute; + right: 0; + top: 0; + padding: 10px; +} +table.jsoneditor-search input, +table.jsoneditor-search div.jsoneditor-results { + font-family: arial, sans-serif; + font-size: 10pt; + color: #1A1A1A; + background: transparent; + /* For Firefox */ +} + +table.jsoneditor-search div.jsoneditor-results { + color: white; + padding-right: 5px; + line-height: 24px; +} + +table.jsoneditor-search { + position: absolute; + right: 4px; + top: 4px; + border-collapse: collapse; + border-spacing: 0; +} + +table.jsoneditor-search div.jsoneditor-frame { + border: 1px solid transparent; + background-color: white; + padding: 0 2px; + margin: 0; +} + +table.jsoneditor-search div.jsoneditor-frame table { + border-collapse: collapse; +} + +table.jsoneditor-search input { + width: 120px; + border: none; + outline: none; + margin: 1px; + line-height: 20px; +} + +table.jsoneditor-search button { + width: 16px; + height: 24px; + padding: 0; + margin: 0; + border: none; + background: url("img/jsoneditor-icons.svg"); + vertical-align: top; +} + +table.jsoneditor-search button:hover { + background-color: transparent; +} + +table.jsoneditor-search button.jsoneditor-refresh { + width: 18px; + background-position: -99px -73px; +} + +table.jsoneditor-search button.jsoneditor-next { + cursor: pointer; + background-position: -124px -73px; +} + +table.jsoneditor-search button.jsoneditor-next:hover { + background-position: -124px -49px; +} + +table.jsoneditor-search button.jsoneditor-previous { + cursor: pointer; + background-position: -148px -73px; + margin-right: 2px; +} + +table.jsoneditor-search button.jsoneditor-previous:hover { + background-position: -148px -49px; +} \ No newline at end of file diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 01826b8e10..f5e7ffea63 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -11,14 +11,18 @@ Properties + + + +

@@ -58,9 +62,18 @@
+
- +
+
+ + + +
+
+
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 5898f85e90..bf477a3ed5 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -28,7 +28,7 @@ var colorPickers = []; debugPrint = function(message) { EventBridge.emitWebEvent( JSON.stringify({ - type:"print", + type: "print", message: message }) ); @@ -40,6 +40,7 @@ function enableChildren(el, selector) { els[i].removeAttribute('disabled'); } } + function disableChildren(el, selector) { els = el.querySelectorAll(selector); for (var i = 0; i < els.length; i++) { @@ -50,14 +51,26 @@ function disableChildren(el, selector) { function enableProperties() { enableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); enableChildren(document, ".colpick"); + var elLocked = document.getElementById("property-locked"); + + if (elLocked.checked === false) { + removeStaticUserData(); + } } + function disableProperties() { disableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); disableChildren(document, ".colpick"); for (var i = 0; i < colorPickers.length; i++) { colorPickers[i].colpickHide(); } + var elLocked = document.getElementById("property-locked"); + + if ($('#userdata-editor').css('display') === "block" && elLocked.checked === true) { + showStaticUserData(); + } + } function showElements(els, show) { @@ -85,7 +98,7 @@ function createEmitCheckedToStringPropertyUpdateFunction(checkboxElement, name, } function createEmitGroupCheckedPropertyUpdateFunction(group, propertyName) { - return function () { + return function() { var properties = {}; properties[group] = {}; properties[group][propertyName] = this.checked; @@ -108,6 +121,7 @@ function createEmitNumberPropertyUpdateFunction(propertyName, decimals) { ); }; } + function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) { return function() { var properties = {}; @@ -127,6 +141,7 @@ function createEmitTextPropertyUpdateFunction(propertyName) { return function() { var properties = {}; properties[propertyName] = this.value; + console.log('properties at set thingo yo') EventBridge.emitWebEvent( JSON.stringify({ type: "update", @@ -136,7 +151,7 @@ function createEmitTextPropertyUpdateFunction(propertyName) { }; } -function createEmitGroupTextPropertyUpdateFunction(group,propertyName) { +function createEmitGroupTextPropertyUpdateFunction(group, propertyName) { return function() { var properties = {}; properties[group] = {}; @@ -153,14 +168,13 @@ function createEmitGroupTextPropertyUpdateFunction(group,propertyName) { function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) { return function() { var data = { - type: "update", - properties: { - } + type: "update", + properties: {} }; data.properties[property] = { - x: elX.value, - y: elY.value, - z: elZ.value, + x: elX.value, + y: elY.value, + z: elZ.value, }; EventBridge.emitWebEvent(JSON.stringify(data)); } @@ -169,15 +183,14 @@ function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) { function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, elZ) { return function() { var data = { - type: "update", - properties: { - } + type: "update", + properties: {} }; - data.properties[group] = { }; + data.properties[group] = {}; data.properties[group][property] = { - x: elX.value, - y: elY.value, - z: elZ ? elZ.value : 0, + x: elX.value, + y: elY.value, + z: elZ ? elZ.value : 0, }; EventBridge.emitWebEvent(JSON.stringify(data)); } @@ -186,14 +199,13 @@ function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, el function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) { return function() { var data = { - type: "update", - properties: { - } + type: "update", + properties: {} }; data.properties[property] = { - x: elX.value * multiplier, - y: elY.value * multiplier, - z: elZ.value * multiplier, + x: elX.value * multiplier, + y: elY.value * multiplier, + z: elZ.value * multiplier, }; EventBridge.emitWebEvent(JSON.stringify(data)); } @@ -206,42 +218,40 @@ function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) }; function emitColorPropertyUpdate(property, red, green, blue, group) { - var data = { - type: "update", - properties: { - } + var data = { + type: "update", + properties: {} + }; + if (group) { + data.properties[group] = {}; + data.properties[group][property] = { + red: red, + green: green, + blue: blue, }; - if (group) { - data.properties[group] = { }; - data.properties[group][property] = { - red: red, - green: green, - blue: blue, - }; - } else { - data.properties[property] = { - red: red, - green: green, - blue: blue, - }; - } - EventBridge.emitWebEvent(JSON.stringify(data)); + } else { + data.properties[property] = { + red: red, + green: green, + blue: blue, + }; + } + EventBridge.emitWebEvent(JSON.stringify(data)); }; function createEmitGroupColorPropertyUpdateFunction(group, property, elRed, elGreen, elBlue) { return function() { var data = { - type: "update", - properties: { - } + type: "update", + properties: {} }; - data.properties[group] = { }; + data.properties[group] = {}; data.properties[group][property] = { - red: elRed.value, - green: elGreen.value, - blue: elBlue.value, + red: elRed.value, + green: elGreen.value, + blue: elBlue.value, }; EventBridge.emitWebEvent(JSON.stringify(data)); } @@ -251,30 +261,65 @@ function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElemen if (subPropertyElement.checked) { if (propertyValue.indexOf(subPropertyString)) { propertyValue += subPropertyString + ','; - } + } } else { // We've unchecked, so remove propertyValue = propertyValue.replace(subPropertyString + ",", ""); } - var _properties ={} + var _properties = {} _properties[propertyName] = propertyValue; - + EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: _properties - }) + JSON.stringify({ + type: "update", + properties: _properties + }) ); } +function setUserDataFromEditor() { + var json = null; + try { + json = editor.get(); + console.log('its good json') + } catch (e) { + console.log('failed to parse json', e) + alert('Invalid JSON code - look for red X in your code ', +e) + } + if (json === null) { + return; + } else { + var text = editor.getText() + console.log('editor text at send:', text) + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: { + userData: text + }, + }) + ); + } + + +} + + function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, defaultValue) { var properties = {}; var parsedData = {}; try { - parsedData = JSON.parse(userDataElement.value); - } catch(e) {} + if ($('#userdata-editor').css('height') === "0px") { + console.log('GET JSON FROM EDITOR') + parsedData = editor.getJSON(); + } else { + console.log('GET JSON FROM TEXT AREA'); + parsedData = JSON.parse(userDataElement.value); + + } + } catch (e) {} if (!(groupName in parsedData)) { parsedData[groupName] = {} @@ -306,9 +351,95 @@ function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, d function setTextareaScrolling(element) { var isScrolling = element.scrollHeight > element.offsetHeight; element.setAttribute("scrolling", isScrolling ? "true" : "false"); +}; + +var editor = null; + +function createJSONEditor() { + var container = document.getElementById("userdata-editor"); + var options = { + search: false, + mode: 'tree', + modes: ['code', 'tree'], + name: 'userData', + onModeChange: function() { + $('.jsoneditor-poweredBy').remove(); + }, + onError: function(e) { + alert('JSON editor:' + e) + }, + onChange: function() { + console.log('editor did change') + } + }; + editor = new JSONEditor(container, options); +}; + +function hideNewJSONEditorButton() { + $('#userdata-new-editor').hide(); + +}; + +function hideClearUserDataButton() { + $('#userdata-clear').hide(); +}; + +function showSaveUserDataButton() { + $('#userdata-save').show(); } -function loaded() { +function hideSaveUserDataButton() { + $('#userdata-save').hide(); + +} + +function showNewJSONEditorButton() { + $('#userdata-new-editor').show(); + +}; + +function showClearUserDataButton() { + $('#userdata-clear').show(); + +}; + +function showUserDataTextArea() { + $('#property-user-data').show(); +}; + +function hideUserDataTextArea() { + $('#property-user-data').hide(); +}; + +function showStaticUserData() { + console.log('showing static userdata') + $('#static-userdata').show(); + $('#static-userdata').css('height', $('#userdata-editor').height()) + $('#static-userdata').text(editor.getText()); +}; + +function removeStaticUserData() { + console.log('hiding static userdata') + $('#static-userdata').hide(); +}; + +function setEditorJSON(json) { + return editor.set(json) +}; + +function getEditorJSON() { + return editor.get(); +}; + +function deleteJSONEditor() { + console.log('should delete editor') + if (editor !== null) { + console.log('has one so do it') + editor.destroy(); + } +}; + +function loaded() { openEventBridge(function() { var allSections = []; var elID = document.getElementById("property-id"); @@ -364,7 +495,7 @@ function loaded() { var elDensity = document.getElementById("property-density"); var elCollisionless = document.getElementById("property-collisionless"); - var elDynamic = document.getElementById("property-dynamic" ); + var elDynamic = document.getElementById("property-dynamic"); var elCollideStatic = document.getElementById("property-collide-static"); var elCollideDynamic = document.getElementById("property-collide-dynamic"); var elCollideKinematic = document.getElementById("property-collide-kinematic"); @@ -384,7 +515,10 @@ function loaded() { */ var elReloadScriptButton = document.getElementById("reload-script-button"); var elUserData = document.getElementById("property-user-data"); - + var elClearUserData = document.getElementById("userdata-clear"); + var elSaveUserData = document.getElementById("userdata-save"); + var elJSONEditor = document.getElementById("userdata-editor"); + var elNewJSONEditor = document.getElementById('userdata-new-editor'); var elColorSections = document.querySelectorAll(".color-section"); var elColor = document.getElementById("property-color"); var elColorRed = document.getElementById("property-color-red"); @@ -394,7 +528,7 @@ function loaded() { var elShapeSections = document.querySelectorAll(".shape-section"); allSections.push(elShapeSections); var elShape = document.getElementById("property-shape"); - + var elLightSections = document.querySelectorAll(".light-section"); allSections.push(elLightSections); var elLightSpotLight = document.getElementById("property-light-spot-light"); @@ -431,9 +565,9 @@ function loaded() { var elDescription = document.getElementById("property-description"); var elHyperlinkHref = document.getElementById("property-hyperlink-href"); - + var elHyperlinkSections = document.querySelectorAll(".hyperlink-section"); - + var elTextSections = document.querySelectorAll(".text-section"); allSections.push(elTextSections); @@ -533,7 +667,7 @@ function loaded() { disableProperties(); } else { - + properties = data.selections[0].properties; @@ -545,12 +679,6 @@ function loaded() { elLocked.checked = properties.locked; - if (properties.locked) { - disableProperties(); - elLocked.removeAttribute('disabled'); - } else { - enableProperties(); - } elName.value = properties.name; @@ -612,7 +740,7 @@ function loaded() { var parsedUserData = {} try { parsedUserData = JSON.parse(properties.userData); - + if ("grabbableKey" in parsedUserData) { if ("grabbable" in parsedUserData["grabbableKey"]) { elGrabbable.checked = parsedUserData["grabbableKey"].grabbable; @@ -624,7 +752,7 @@ function loaded() { elIgnoreIK.checked = parsedUserData["grabbableKey"].ignoreIK; } } - } catch(e) {} + } catch (e) {} elCollisionSoundURL.value = properties.collisionSoundURL; elLifetime.value = properties.lifetime; @@ -633,8 +761,29 @@ function loaded() { FIXME: See FIXME for property-script-url. elScriptTimestamp.value = properties.scriptTimestamp; */ - elUserData.value = properties.userData; - setTextareaScrolling(elUserData); + deleteJSONEditor(); + hideUserDataTextArea(); + var json = null; + try { + json = JSON.parse(properties.userData) + //its json + if (Object.keys(json).length === 0 && json.constructor === Object) { + //it's an empty object + console.log('empty object') + } + createJSONEditor(); + setEditorJSON(json) + showSaveUserDataButton(); + hideNewJSONEditorButton(); + console.log('did parse json successfully') + + } catch (e) { + console.log('error parsing json') + elUserData.value = properties.userData; + showUserDataTextArea(); + hideSaveUserDataButton(); + //normal text + } elHyperlinkHref.value = properties.href; elDescription.value = properties.description; @@ -643,7 +792,7 @@ function loaded() { for (var j = 0; j < allSections[i].length; j++) { allSections[i][j].style.display = 'none'; } - } + } for (var i = 0; i < elHyperlinkSections.length; i++) { elHyperlinkSections[i].style.display = 'table'; @@ -661,7 +810,7 @@ function loaded() { elShapeSections[i].style.display = 'none'; } } - + if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") { for (var i = 0; i < elColorSections.length; i++) { elColorSections[i].style.display = 'table'; @@ -669,7 +818,7 @@ function loaded() { elColorRed.value = properties.color.red; elColorGreen.value = properties.color.green; elColorBlue.value = properties.color.blue; - elColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; + elColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; } else { for (var i = 0; i < elColorSections.length; i++) { elColorSections[i].style.display = 'none'; @@ -714,7 +863,7 @@ function loaded() { elTextText.value = properties.text; elTextLineHeight.value = properties.lineHeight.toFixed(4); elTextFaceCamera = properties.faceCamera; - elTextTextColor.style.backgroundColor = "rgb(" + properties.textColor.red + "," + properties.textColor.green + "," + properties.textColor.blue + ")"; + elTextTextColor.style.backgroundColor = "rgb(" + properties.textColor.red + "," + properties.textColor.green + "," + properties.textColor.blue + ")"; elTextTextColorRed.value = properties.textColor.red; elTextTextColorGreen.value = properties.textColor.green; elTextTextColorBlue.value = properties.textColor.blue; @@ -728,7 +877,7 @@ function loaded() { elLightSpotLight.checked = properties.isSpotlight; - elLightColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; + elLightColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")"; elLightColorRed.value = properties.color.red; elLightColorGreen.value = properties.color.green; elLightColorBlue.value = properties.color.blue; @@ -743,7 +892,7 @@ function loaded() { } elZoneStageSunModelEnabled.checked = properties.stage.sunModelEnabled; - elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")"; + elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")"; elZoneKeyLightColorRed.value = properties.keyLight.color.red; elZoneKeyLightColorGreen.value = properties.keyLight.color.green; elZoneKeyLightColorBlue.value = properties.keyLight.color.blue; @@ -766,7 +915,7 @@ function loaded() { elZoneBackgroundMode.value = properties.backgroundMode; setDropdownText(elZoneBackgroundMode); - elZoneSkyboxColor.style.backgroundColor = "rgb(" + properties.skybox.color.red + "," + properties.skybox.color.green + "," + properties.skybox.color.blue + ")"; + elZoneSkyboxColor.style.backgroundColor = "rgb(" + properties.skybox.color.red + "," + properties.skybox.color.green + "," + properties.skybox.color.blue + ")"; elZoneSkyboxColorRed.value = properties.skybox.color.red; elZoneSkyboxColorGreen.value = properties.skybox.color.green; elZoneSkyboxColorBlue.value = properties.skybox.color.blue; @@ -790,10 +939,17 @@ function loaded() { elYTextureURL.value = properties.yTextureURL; elZTextureURL.value = properties.zTextureURL; } - + + if (properties.locked) { + disableProperties(); + elLocked.removeAttribute('disabled'); + } else { + enableProperties(); + } + var activeElement = document.activeElement; - - if(typeof activeElement.select!=="undefined"){ + + if (typeof activeElement.select !== "undefined") { activeElement.select(); } } @@ -903,8 +1059,48 @@ function loaded() { FIXME: See FIXME for property-script-url. elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp')); */ + + + elClearUserData.addEventListener("click", function() { + deleteJSONEditor(); + console.log('CLEAR USER DATA WAS CLICKED w') + elUserData.value = ""; + showUserDataTextArea(); + console.log('CLEAR USER DATA WAS CLICKED x') + showNewJSONEditorButton(); + console.log('CLEAR USER DATA WAS CLICKED y') + hideSaveUserDataButton(); + console.log('CLEAR USER DATA WAS CLICKED z') + var properties = {}; + properties['userData'] = elUserData.value; + console.log('properties at set thingo yo', elUserData.value) + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); + + + }); + + elSaveUserData.addEventListener("click", function() { + console.log('click on save json button') + setUserDataFromEditor(); + }); + elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); + elNewJSONEditor.addEventListener('click', function() { + deleteJSONEditor(); + createJSONEditor(); + var data = {}; + setEditorJSON(data); + hideUserDataTextArea(); + hideNewJSONEditorButton(); + showSaveUserDataButton(); + }); + var colorChangeFunction = createEmitColorPropertyUpdateFunction( 'color', elColorRed, elColorGreen, elColorBlue); elColorRed.addEventListener('change', colorChangeFunction); @@ -914,13 +1110,13 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', - onShow: function (colpick) { + onShow: function(colpick) { $('#property-color').attr('active', 'true'); }, - onHide: function (colpick) { + onHide: function(colpick) { $('#property-color').attr('active', 'false'); }, - onSubmit: function (hsb, hex, rgb, el) { + onSubmit: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); $(el).colpickHide(); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); @@ -938,13 +1134,13 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', - onShow: function (colpick) { + onShow: function(colpick) { $('#property-light-color').attr('active', 'true'); }, - onHide: function (colpick) { + onHide: function(colpick) { $('#property-light-color').attr('active', 'false'); }, - onSubmit: function (hsb, hex, rgb, el) { + onSubmit: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); $(el).colpickHide(); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); @@ -965,8 +1161,8 @@ function loaded() { elCompoundShapeURL.addEventListener('change', createEmitTextPropertyUpdateFunction('compoundShapeURL')); elModelAnimationURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('animation', 'url')); - elModelAnimationPlaying.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation','running')); - elModelAnimationFPS.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation','fps')); + elModelAnimationPlaying.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'running')); + elModelAnimationFPS.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'fps')); elModelAnimationFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'currentFrame')); elModelAnimationFirstFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'firstFrame')); elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame')); @@ -984,17 +1180,17 @@ function loaded() { elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction); elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction); colorPickers.push($('#property-text-text-color').colpick({ - colorScheme:'dark', - layout:'hex', + colorScheme: 'dark', + layout: 'hex', color: '000000', - onShow: function (colpick) { + onShow: function(colpick) { $('#property-text-text-color').attr('active', 'true'); }, - onHide: function (colpick) { + onHide: function(colpick) { $('#property-text-text-color').attr('active', 'false'); }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#'+hex); + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); $(el).colpickHide(); $(el).attr('active', 'false'); emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b); @@ -1007,82 +1203,82 @@ function loaded() { elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); colorPickers.push($('#property-text-background-color').colpick({ - colorScheme:'dark', - layout:'hex', - color:'000000', - onShow: function (colpick) { + colorScheme: 'dark', + layout: 'hex', + color: '000000', + onShow: function(colpick) { $('#property-text-background-color').attr('active', 'true'); }, - onHide: function (colpick) { + onHide: function(colpick) { $('#property-text-background-color').attr('active', 'false'); }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#'+hex); + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); $(el).colpickHide(); emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b); } })); - elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','sunModelEnabled')); + elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage', 'sunModelEnabled')); colorPickers.push($('#property-zone-key-light-color').colpick({ - colorScheme:'dark', - layout:'hex', - color:'000000', - onShow: function (colpick) { + colorScheme: 'dark', + layout: 'hex', + color: '000000', + onShow: function(colpick) { $('#property-zone-key-light-color').attr('active', 'true'); }, - onHide: function (colpick) { + onHide: function(colpick) { $('#property-zone-key-light-color').attr('active', 'false'); }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#'+hex); + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); $(el).colpickHide(); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight'); } })); - var zoneKeyLightColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('keyLight','color', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue); + var zoneKeyLightColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('keyLight', 'color', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue); elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction); elZoneKeyLightColorGreen.addEventListener('change', zoneKeyLightColorChangeFunction); elZoneKeyLightColorBlue.addEventListener('change', zoneKeyLightColorChangeFunction); - elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','intensity')); - elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','ambientIntensity')); - elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight','ambientURL')); - var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight','direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY); + elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight', 'intensity')); + elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight', 'ambientIntensity')); + elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight', 'ambientURL')); + var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight', 'direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY); elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction); elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction); - elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude')); - elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude')); - elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude')); - elZoneStageAutomaticHourDay.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','automaticHourDay')); - elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','day')); - elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','hour')); + elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'latitude')); + elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'longitude')); + elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'altitude')); + elZoneStageAutomaticHourDay.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage', 'automaticHourDay')); + elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'day')); + elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'hour')); elZoneBackgroundMode.addEventListener('change', createEmitTextPropertyUpdateFunction('backgroundMode')); - var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox','color', + var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox', 'color', elZoneSkyboxColorRed, elZoneSkyboxColorGreen, elZoneSkyboxColorBlue); elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction); elZoneSkyboxColorGreen.addEventListener('change', zoneSkyboxColorChangeFunction); elZoneSkyboxColorBlue.addEventListener('change', zoneSkyboxColorChangeFunction); colorPickers.push($('#property-zone-skybox-color').colpick({ - colorScheme:'dark', - layout:'hex', - color:'000000', - onShow: function (colpick) { + colorScheme: 'dark', + layout: 'hex', + color: '000000', + onShow: function(colpick) { $('#property-zone-skybox-color').attr('active', 'true'); }, - onHide: function (colpick) { + onHide: function(colpick) { $('#property-zone-skybox-color').attr('active', 'false'); }, - onSubmit: function (hsb, hex, rgb, el) { - $(el).css('background-color', '#'+hex); + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); $(el).colpickHide(); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox'); } })); - elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url')); + elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox', 'url')); elZoneFlyingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('flyingAllowed')); elZoneGhostingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ghostingAllowed')); @@ -1169,7 +1365,7 @@ function loaded() { // Collapsible sections var elCollapsible = document.getElementsByClassName("section-header"); - var toggleCollapsedEvent = function (event) { + var toggleCollapsedEvent = function(event) { var element = event.target; if (element.nodeName !== "DIV") { element = element.parentNode; @@ -1188,7 +1384,7 @@ function loaded() { // Textarea scrollbars var elTextareas = document.getElementsByTagName("TEXTAREA"); - var textareaOnChangeEvent = function (event) { + var textareaOnChangeEvent = function(event) { setTextareaScrolling(event.target); } @@ -1274,7 +1470,7 @@ function loaded() { dt.appendChild(span); var span = document.createElement("span"); - span.textContent = "5"; // caratDn + span.textContent = "5"; // caratDn dt.appendChild(span); var dd = document.createElement("dd"); @@ -1302,8 +1498,7 @@ function loaded() { augmentSpinButtons(); // Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked - document.addEventListener("contextmenu", function (event) { + document.addEventListener("contextmenu", function(event) { event.preventDefault(); }, false); -} - +} \ No newline at end of file diff --git a/scripts/system/html/js/jsoneditor.min.js b/scripts/system/html/js/jsoneditor.min.js new file mode 100644 index 0000000000..12e8a07378 --- /dev/null +++ b/scripts/system/html/js/jsoneditor.min.js @@ -0,0 +1,49 @@ +/*! + * jsoneditor.js + * + * @brief + * JSONEditor is a web-based tool to view, edit, format, and validate JSON. + * It has various modes such as a tree editor, a code editor, and a plain text + * editor. + * + * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ + * + * @license + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * Copyright (c) 2011-2016 Jos de Jong, http://jsoneditoronline.org + * + * @author Jos de Jong, + * @version 5.5.7 + * @date 2016-08-17 + */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.JSONEditor=t():e.JSONEditor=t()}(this,function(){return function(e){function t(n){if(i[n])return i[n].exports;var r=i[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var i={};return t.m=e,t.c=i,t.p="",t(0)}([function(e,t,i){"use strict";function n(e,t,i){if(!(this instanceof n))throw new Error('JSONEditor constructor called without "new".');var r=l.getInternetExplorerVersion();if(-1!=r&&9>r)throw new Error("Unsupported browser, IE9 or newer required. Please install the newest version of your browser.");if(t&&(t.error&&(console.warn('Option "error" has been renamed to "onError"'),t.onError=t.error,delete t.error),t.change&&(console.warn('Option "change" has been renamed to "onChange"'),t.onChange=t.change,delete t.change),t.editable&&(console.warn('Option "editable" has been renamed to "onEditable"'),t.onEditable=t.editable,delete t.editable),t)){var o=["ace","theme","ajv","schema","onChange","onEditable","onError","onModeChange","escapeUnicode","history","search","mode","modes","name","indentation","sortObjectKeys"];Object.keys(t).forEach(function(e){-1===o.indexOf(e)&&console.warn('Unknown option "'+e+'". This option will be ignored')})}arguments.length&&this._create(e,t,i)}var r;try{r=i(1)}catch(o){}var s=i(51),a=i(62),l=i(54);n.modes={},n.prototype.DEBOUNCE_INTERVAL=150,n.prototype._create=function(e,t,i){this.container=e,this.options=t||{},this.json=i||{};var n=this.options.mode||"tree";this.setMode(n)},n.prototype.destroy=function(){},n.prototype.set=function(e){this.json=e},n.prototype.get=function(){return this.json},n.prototype.setText=function(e){this.json=l.parse(e)},n.prototype.getText=function(){return JSON.stringify(this.json)},n.prototype.setName=function(e){this.options||(this.options={}),this.options.name=e},n.prototype.getName=function(){return this.options&&this.options.name},n.prototype.setMode=function(e){var t,i,r=this.container,o=l.extend({},this.options),s=o.mode;o.mode=e;var a=n.modes[e];if(!a)throw new Error('Unknown mode "'+o.mode+'"');try{var c="text"==a.data;if(i=this.getName(),t=this[c?"getText":"get"](),this.destroy(),l.clear(this),l.extend(this,a.mixin),this.create(r,o),this.setName(i),this[c?"setText":"set"](t),"function"==typeof a.load)try{a.load.call(this)}catch(h){console.error(h)}if("function"==typeof o.onModeChange&&e!==s)try{o.onModeChange(e,s)}catch(h){console.error(h)}}catch(h){this._onError(h)}},n.prototype.getMode=function(){return this.options.mode},n.prototype._onError=function(e){if(!this.options||"function"!=typeof this.options.onError)throw e;this.options.onError(e)},n.prototype.setSchema=function(e){if(e){var t;try{t=this.options.ajv||r({allErrors:!0,verbose:!0})}catch(i){console.warn("Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.")}t&&(this.validateSchema=t.compile(e),this.options.schema=e,this.validate()),this.refresh()}else this.validateSchema=null,this.options.schema=null,this.validate(),this.refresh()},n.prototype.validate=function(){},n.prototype.refresh=function(){},n.registerMode=function(e){var t,i;if(l.isArray(e))for(t=0;t",'"',"`"," ","\r","\n"," "],g=["{","}","|","\\","^","`"].concat(m),v=["'"].concat(g),w=["%","/","?",";","#"].concat(v),y=["/","?","#"],A=255,C=/^[a-z0-9A-Z_-]{0,63}$/,E=/^([a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,"javascript:":!0},F={javascript:!0,"javascript:":!0},x={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},S=i(7);n.prototype.parse=function(e,t,i){if(!l(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var n=e;n=n.trim();var r=f.exec(n);if(r){r=r[0];var o=r.toLowerCase();this.protocol=o,n=n.substr(r.length)}if(i||r||n.match(/^\/\/[^@\/]+@[^@\/]+/)){var s="//"===n.substr(0,2);!s||r&&F[r]||(n=n.substr(2),this.slashes=!0)}if(!F[r]&&(s||r&&!x[r])){for(var a=-1,c=0;ch)&&(a=h)}var d,p;p=-1===a?n.lastIndexOf("@"):n.lastIndexOf("@",a),-1!==p&&(d=n.slice(0,p),n=n.slice(p+1),this.auth=decodeURIComponent(d)),a=-1;for(var c=0;ch)&&(a=h)}-1===a&&(a=n.length),this.host=n.slice(0,a),n=n.slice(a),this.parseHost(),this.hostname=this.hostname||"";var m="["===this.hostname[0]&&"]"===this.hostname[this.hostname.length-1];if(!m)for(var g=this.hostname.split(/\./),c=0,$=g.length;$>c;c++){var D=g[c];if(D&&!D.match(C)){for(var k="",B=0,_=D.length;_>B;B++)k+=D.charCodeAt(B)>127?"x":D[B];if(!k.match(C)){var L=g.slice(0,c),R=g.slice(c+1),T=D.match(E);T&&(L.push(T[1]),R.unshift(T[2])),R.length&&(n="/"+R.join(".")+n),this.hostname=L.join(".");break}}}if(this.hostname.length>A?this.hostname="":this.hostname=this.hostname.toLowerCase(),!m){for(var P=this.hostname.split("."),M=[],c=0;cc;c++){var j=v[c],W=encodeURIComponent(j);W===j&&(W=escape(j)),n=n.split(j).join(W)}var H=n.indexOf("#");-1!==H&&(this.hash=n.substr(H),n=n.slice(0,H));var V=n.indexOf("?");if(-1!==V?(this.search=n.substr(V),this.query=n.substr(V+1),t&&(this.query=S.parse(this.query)),n=n.slice(0,V)):t&&(this.search="",this.query={}),n&&(this.pathname=n),x[o]&&this.hostname&&!this.pathname&&(this.pathname="/"),this.pathname||this.search){var N=this.pathname||"",O=this.search||"";this.path=N+O}return this.href=this.format(),this},n.prototype.format=function(){var e=this.auth||"";e&&(e=encodeURIComponent(e),e=e.replace(/%3A/i,":"),e+="@");var t=this.protocol||"",i=this.pathname||"",n=this.hash||"",r=!1,o="";this.host?r=e+this.host:this.hostname&&(r=e+(-1===this.hostname.indexOf(":")?this.hostname:"["+this.hostname+"]"),this.port&&(r+=":"+this.port)),this.query&&c(this.query)&&Object.keys(this.query).length&&(o=S.stringify(this.query));var s=this.search||o&&"?"+o||"";return t&&":"!==t.substr(-1)&&(t+=":"),this.slashes||(!t||x[t])&&r!==!1?(r="//"+(r||""),i&&"/"!==i.charAt(0)&&(i="/"+i)):r||(r=""),n&&"#"!==n.charAt(0)&&(n="#"+n),s&&"?"!==s.charAt(0)&&(s="?"+s),i=i.replace(/[?#]/g,function(e){return encodeURIComponent(e)}),s=s.replace("#","%23"),t+r+i+s+n},n.prototype.resolve=function(e){return this.resolveObject(r(e,!1,!0)).format()},n.prototype.resolveObject=function(e){if(l(e)){var t=new n;t.parse(e,!1,!0),e=t}var i=new n;if(Object.keys(this).forEach(function(e){i[e]=this[e]},this),i.hash=e.hash,""===e.href)return i.href=i.format(),i;if(e.slashes&&!e.protocol)return Object.keys(e).forEach(function(t){"protocol"!==t&&(i[t]=e[t])}),x[i.protocol]&&i.hostname&&!i.pathname&&(i.path=i.pathname="/"),i.href=i.format(),i;if(e.protocol&&e.protocol!==i.protocol){if(!x[e.protocol])return Object.keys(e).forEach(function(t){i[t]=e[t]}),i.href=i.format(),i;if(i.protocol=e.protocol,e.host||F[e.protocol])i.pathname=e.pathname;else{for(var r=(e.pathname||"").split("/");r.length&&!(e.host=r.shift()););e.host||(e.host=""),e.hostname||(e.hostname=""),""!==r[0]&&r.unshift(""),r.length<2&&r.unshift(""),i.pathname=r.join("/")}if(i.search=e.search,i.query=e.query,i.host=e.host||"",i.auth=e.auth,i.hostname=e.hostname||e.host,i.port=e.port,i.pathname||i.search){var o=i.pathname||"",s=i.search||"";i.path=o+s}return i.slashes=i.slashes||e.slashes,i.href=i.format(),i}var a=i.pathname&&"/"===i.pathname.charAt(0),c=e.host||e.pathname&&"/"===e.pathname.charAt(0),u=c||a||i.host&&e.pathname,f=u,p=i.pathname&&i.pathname.split("/")||[],r=e.pathname&&e.pathname.split("/")||[],m=i.protocol&&!x[i.protocol];if(m&&(i.hostname="",i.port=null,i.host&&(""===p[0]?p[0]=i.host:p.unshift(i.host)),i.host="",e.protocol&&(e.hostname=null,e.port=null,e.host&&(""===r[0]?r[0]=e.host:r.unshift(e.host)),e.host=null),u=u&&(""===r[0]||""===p[0])),c)i.host=e.host||""===e.host?e.host:i.host,i.hostname=e.hostname||""===e.hostname?e.hostname:i.hostname,i.search=e.search,i.query=e.query,p=r;else if(r.length)p||(p=[]),p.pop(),p=p.concat(r),i.search=e.search,i.query=e.query;else if(!d(e.search)){if(m){i.hostname=i.host=p.shift();var g=i.host&&i.host.indexOf("@")>0?i.host.split("@"):!1;g&&(i.auth=g.shift(),i.host=i.hostname=g.shift())}return i.search=e.search,i.query=e.query,h(i.pathname)&&h(i.search)||(i.path=(i.pathname?i.pathname:"")+(i.search?i.search:"")),i.href=i.format(),i}if(!p.length)return i.pathname=null,i.search?i.path="/"+i.search:i.path=null,i.href=i.format(),i;for(var v=p.slice(-1)[0],w=(i.host||e.host)&&("."===v||".."===v)||""===v,y=0,A=p.length;A>=0;A--)v=p[A],"."==v?p.splice(A,1):".."===v?(p.splice(A,1),y++):y&&(p.splice(A,1),y--);if(!u&&!f)for(;y--;y)p.unshift("..");!u||""===p[0]||p[0]&&"/"===p[0].charAt(0)||p.unshift(""),w&&"/"!==p.join("/").substr(-1)&&p.push("");var C=""===p[0]||p[0]&&"/"===p[0].charAt(0);if(m){i.hostname=i.host=C?"":p.length?p.shift():"";var g=i.host&&i.host.indexOf("@")>0?i.host.split("@"):!1;g&&(i.auth=g.shift(),i.host=i.hostname=g.shift())}return u=u||i.host&&p.length,u&&!C&&p.unshift(""),p.length?i.pathname=p.join("/"):(i.pathname=null,i.path=null),h(i.pathname)&&h(i.search)||(i.path=(i.pathname?i.pathname:"")+(i.search?i.search:"")),i.auth=e.auth||i.auth,i.slashes=i.slashes||e.slashes,i.href=i.format(),i},n.prototype.parseHost=function(){var e=this.host,t=p.exec(e);t&&(t=t[0],":"!==t&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,i){var n;(function(e,r){!function(o){function s(e){throw RangeError(L[e])}function a(e,t){for(var i=e.length,n=[];i--;)n[i]=t(e[i]);return n}function l(e,t){var i=e.split("@"),n="";i.length>1&&(n=i[0]+"@",e=i[1]),e=e.replace(_,".");var r=e.split("."),o=a(r,t).join(".");return n+o}function c(e){for(var t,i,n=[],r=0,o=e.length;o>r;)t=e.charCodeAt(r++),t>=55296&&56319>=t&&o>r?(i=e.charCodeAt(r++),56320==(64512&i)?n.push(((1023&t)<<10)+(1023&i)+65536):(n.push(t),r--)):n.push(t);return n}function h(e){return a(e,function(e){var t="";return e>65535&&(e-=65536,t+=P(e>>>10&1023|55296),e=56320|1023&e),t+=P(e)}).join("")}function d(e){return 10>e-48?e-22:26>e-65?e-65:26>e-97?e-97:C}function u(e,t){return e+22+75*(26>e)-((0!=t)<<5)}function f(e,t,i){var n=0;for(e=i?T(e/x):e>>1,e+=T(e/t);e>R*b>>1;n+=C)e=T(e/R);return T(n+(R+1)*e/(e+F))}function p(e){var t,i,n,r,o,a,l,c,u,p,m=[],g=e.length,v=0,w=$,y=S;for(i=e.lastIndexOf(D),0>i&&(i=0),n=0;i>n;++n)e.charCodeAt(n)>=128&&s("not-basic"),m.push(e.charCodeAt(n));for(r=i>0?i+1:0;g>r;){for(o=v,a=1,l=C;r>=g&&s("invalid-input"),c=d(e.charCodeAt(r++)),(c>=C||c>T((A-v)/a))&&s("overflow"),v+=c*a,u=y>=l?E:l>=y+b?b:l-y,!(u>c);l+=C)p=C-u,a>T(A/p)&&s("overflow"),a*=p;t=m.length+1,y=f(v-o,t,0==o),T(v/t)>A-w&&s("overflow"),w+=T(v/t),v%=t,m.splice(v++,0,w)}return h(m)}function m(e){var t,i,n,r,o,a,l,h,d,p,m,g,v,w,y,F=[];for(e=c(e),g=e.length,t=$,i=0,o=S,a=0;g>a;++a)m=e[a],128>m&&F.push(P(m));for(n=r=F.length,r&&F.push(D);g>n;){for(l=A,a=0;g>a;++a)m=e[a],m>=t&&l>m&&(l=m);for(v=n+1,l-t>T((A-i)/v)&&s("overflow"),i+=(l-t)*v,t=l,a=0;g>a;++a)if(m=e[a],t>m&&++i>A&&s("overflow"),m==t){for(h=i,d=C;p=o>=d?E:d>=o+b?b:d-o,!(p>h);d+=C)y=h-p,w=C-p,F.push(P(u(p+y%w,0))),h=T(y/w);F.push(P(u(h,0))),o=f(i,v,n==r),i=0,++n}++i,++t}return F.join("")}function g(e){return l(e,function(e){return k.test(e)?p(e.slice(4).toLowerCase()):e})}function v(e){return l(e,function(e){return B.test(e)?"xn--"+m(e):e})}var w=("object"==typeof t&&t&&!t.nodeType&&t,"object"==typeof e&&e&&!e.nodeType&&e,"object"==typeof r&&r);w.global!==w&&w.window!==w&&w.self!==w||(o=w);var y,A=2147483647,C=36,E=1,b=26,F=38,x=700,S=72,$=128,D="-",k=/^xn--/,B=/[^\x20-\x7E]/,_=/[\x2E\u3002\uFF0E\uFF61]/g,L={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},R=C-E,T=Math.floor,P=String.fromCharCode;y={version:"1.3.2",ucs2:{decode:c,encode:h},decode:p,encode:m,toASCII:v,toUnicode:g},n=function(){return y}.call(t,i,t,e),!(void 0!==n&&(e.exports=n))}(this)}).call(t,i(6)(e),function(){return this}())},function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children=[],e.webpackPolyfill=1),e}},function(e,t,i){"use strict";t.decode=t.parse=i(8),t.encode=t.stringify=i(9)},function(e,t){"use strict";function i(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,n,r){t=t||"&",n=n||"=";var o={};if("string"!=typeof e||0===e.length)return o;var s=/\+/g;e=e.split(t);var a=1e3;r&&"number"==typeof r.maxKeys&&(a=r.maxKeys);var l=e.length;a>0&&l>a&&(l=a);for(var c=0;l>c;++c){var h,d,u,f,p=e[c].replace(s,"%20"),m=p.indexOf(n);m>=0?(h=p.substr(0,m),d=p.substr(m+1)):(h=p,d=""),u=decodeURIComponent(h),f=decodeURIComponent(d),i(o,u)?Array.isArray(o[u])?o[u].push(f):o[u]=[o[u],f]:o[u]=f}return o}},function(e,t){"use strict";var i=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};e.exports=function(e,t,n,r){return t=t||"&",n=n||"=",null===e&&(e=void 0),"object"==typeof e?Object.keys(e).map(function(r){var o=encodeURIComponent(i(r))+n;return Array.isArray(e[r])?e[r].map(function(e){return o+encodeURIComponent(i(e))}).join(t):o+encodeURIComponent(i(e[r]))}).join(t):r?encodeURIComponent(i(r))+n+encodeURIComponent(i(e)):""}},function(e,t){"use strict";e.exports=function i(e,t){if(e===t)return!0;var n,r=Array.isArray(e),o=Array.isArray(t);if(r&&o){if(e.length!=t.length)return!1;for(n=0;nr;)i++,t=e.charCodeAt(r++),t>=55296&&56319>=t&&n>r&&(t=e.charCodeAt(r),56320==(64512&t)&&r++);return i}function d(e,t){t+="[^0-9]";var i=e.match(new RegExp(t,"g"));return i?i.length:0}function u(e,t,i){return t+="([^0-9])",i=i.replace(/\$/g,"$$$$"),e.replace(new RegExp(t,"g"),i+"$1")}function f(e){return e.replace(D,"").replace(k,"").replace(B,"if (!($1))")}function p(e,t){var i=e.match(_);return i&&2===i.length?t?e.replace(R,"").replace(M,O):e.replace(L,"").replace(T,P):e}function m(e,t){for(var i in e)if(t[i])return!0}function g(e){return"'"+c(e)+"'"}function v(e,t,i,n){var r=i?"'/' + "+t+(n?"":".replace(/~/g, '~0').replace(/\\//g, '~1')"):n?"'[' + "+t+" + ']'":"'[\\'' + "+t+" + '\\']'";return A(e,r)}function w(e,t,i){var n=g(i?"/"+b(t):l(t));return A(e,n)}function y(e,t,i){var n=e.match(N);if(!n)throw new Error("Invalid relative JSON-pointer: "+e);var r=+n[1],o=n[2];if("#"==o){if(r>=t)throw new Error("Cannot access property/index "+r+" levels up, current level is "+t);return i[t-r]}if(r>t)throw new Error("Cannot access data "+r+" levels up, current level is "+t);var s="data"+(t-r||"");if(!o)return s;for(var a=s,c=o.split("/"),h=0;h="0"&&"9">=n;)t+=n,l();if("."===n)for(t+=".";l()&&n>="0"&&"9">=n;)t+=n;if("e"===n||"E"===n)for(t+=n,l(),"-"!==n&&"+"!==n||(t+=n,l());n>="0"&&"9">=n;)t+=n,l();return e=+t,isFinite(e)?e:void a("Bad number")},h=function(){var e,t,i,r="";if('"'===n)for(;l();){if('"'===n)return l(),r;if("\\"===n)if(l(),"u"===n){for(i=0,t=0;4>t&&(e=parseInt(l(),16),isFinite(e));t+=1)i=16*i+e;r+=String.fromCharCode(i)}else{if("string"!=typeof s[n])break;r+=s[n]}else r+=n}a("Bad string")},d=function(){for(;n&&" ">=n;)l()},u=function(){switch(n){case"t":return l("t"),l("r"),l("u"),l("e"),!0;case"f":return l("f"),l("a"),l("l"),l("s"),l("e"),!1;case"n":return l("n"),l("u"),l("l"),l("l"),null}a("Unexpected '"+n+"'")},f=function(){var e=[];if("["===n){if(l("["),d(),"]"===n)return l("]"),e;for(;n;){if(e.push(o()),d(),"]"===n)return l("]"),e;l(","),d()}}a("Bad array")},p=function(){var e,t={};if("{"===n){if(l("{"),d(),"}"===n)return l("}"),t;for(;n;){if(e=h(),d(),l(":"),Object.hasOwnProperty.call(t,e)&&a('Duplicate key "'+e+'"'),t[e]=o(),d(),"}"===n)return l("}"),t;l(","),d()}}a("Bad object")};o=function(){switch(d(),n){case"{":return p();case"[":return f();case'"':return h();case"-":return c();default:return n>="0"&&"9">=n?c():u()}},e.exports=function(e,t){var s;return r=e,i=0,n=" ",s=o(),d(),n&&a("Syntax error"),"function"==typeof t?function l(e,i){var n,r,o=e[i];if(o&&"object"==typeof o)for(n in o)Object.prototype.hasOwnProperty.call(o,n)&&(r=l(o,n),void 0!==r?o[n]=r:delete o[n]);return t.call(e,i,o)}({"":s},""):s}},function(e,t){function i(e){return a.lastIndex=0,a.test(e)?'"'+e.replace(a,function(e){var t=l[e];return"string"==typeof t?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function n(e,t){var a,l,c,h,d,u=r,f=t[e];switch(f&&"object"==typeof f&&"function"==typeof f.toJSON&&(f=f.toJSON(e)),"function"==typeof s&&(f=s.call(t,e,f)),typeof f){case"string":return i(f);case"number":return isFinite(f)?String(f):"null";case"boolean":case"null":return String(f);case"object":if(!f)return"null";if(r+=o,d=[],"[object Array]"===Object.prototype.toString.apply(f)){for(h=f.length,a=0;h>a;a+=1)d[a]=n(a,f)||"null";return c=0===d.length?"[]":r?"[\n"+r+d.join(",\n"+r)+"\n"+u+"]":"["+d.join(",")+"]",r=u,c}if(s&&"object"==typeof s)for(h=s.length,a=0;h>a;a+=1)l=s[a],"string"==typeof l&&(c=n(l,f),c&&d.push(i(l)+(r?": ":":")+c));else for(l in f)Object.prototype.hasOwnProperty.call(f,l)&&(c=n(l,f),c&&d.push(i(l)+(r?": ":":")+c));return c=0===d.length?"{}":r?"{\n"+r+d.join(",\n"+r)+"\n"+u+"}":"{"+d.join(",")+"}",r=u,c}}var r,o,s,a=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,l={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};e.exports=function(e,t,i){var a;if(r="",o="","number"==typeof i)for(a=0;i>a;a+=1)o+=" ";else"string"==typeof i&&(o=i);if(s=t,t&&"function"!=typeof t&&("object"!=typeof t||"number"!=typeof t.length))throw new Error("JSON.stringify");return n("",{"":e})}},function(e,t,i){"use strict";function n(e){r.copy(e,this)}var r=i(11);e.exports=n},function(module,exports,__webpack_require__){"use strict";function setupAsync(e,t){t!==!1&&(t=!0);var i,n=e.async,r=e.transpile;switch(typeof r){case"string":var o=TRANSPILE[r];if(!o)throw new Error("bad transpiler: "+r);return e._transpileFunc=o(e,t);case"undefined":case"boolean":if("string"==typeof n){if(i=ASYNC[n],!i)throw new Error("bad async mode: "+n);return e.transpile=i(e,t)}for(var s=0;s$;)S=x[$+=1],$&&(r+=" if ("+b+" === undefined) { ",F+="}"),"string"==S?r+=" if ("+E+" == 'number' || "+E+" == 'boolean') "+b+" = '' + "+c+"; else if ("+c+" === null) "+b+" = ''; ":"number"==S||"integer"==S?(r+=" if ("+E+" == 'boolean' || "+c+" === null || ("+E+" == 'string' && "+c+" && "+c+" == +"+c+" ","integer"==S&&(r+=" && !("+c+" % 1)"),r+=")) "+b+" = +"+c+"; "):"boolean"==S?r+=" if ("+c+" === 'false' || "+c+" === 0 || "+c+" === null) "+b+" = false; else if ("+c+" === 'true' || "+c+" === 1) "+b+" = true; ":"null"==S&&(r+=" if ("+c+" === '' || "+c+" === 0 || "+c+" === false) "+b+" = null; ");r+=" "+F+" if ("+b+" === undefined) { ";var k=k||[];k.push(r),r="",e.createErrors!==!1?(r+=" { keyword: '"+(d||"type")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+A+"\" , params: { type: '",r+=v?""+g.join(","):""+g,r+="' } ",e.opts.messages!==!1&&(r+=" , message: 'should be ",r+=v?""+g.join(","):""+g,r+="' "),e.opts.verbose&&(r+=" , schema: validate.schema"+y+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+c+" "),r+=" } "):r+=" {} ";var B=r;if(r=k.pop(),r+=!e.compositeRule&&f?e.async?" throw new ValidationError(["+B+"]); ":" validate.errors = ["+B+"]; return false; ":" var err = "+B+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",r+=" } else { ",l){var _="data"+(l-1||""),L=e.dataPathArr[l];r+=" "+c+" = "+_+"["+L+"] = "+b+"; "}else r+=" data = "+b+"; if (parentData !== undefined) parentData[parentDataProperty] = "+b+"; ";r+=" } } "}}var R=e.RULES;if(R)for(var T,P=-1,M=R.length-1;M>P;)if(T=R[P+=1],i(T)){if(T.type&&(r+=" if ("+e.util.checkDataType(T.type,c)+") { "),e.opts.useDefaults&&!e.compositeRule)if("object"==T.type&&e.schema.properties){var O=e.schema.properties,N=Object.keys(O),I=N;if(I)for(var j,W=-1,H=I.length-1;H>W;){j=I[W+=1];var V=O[j];if(void 0!==V["default"]){var z=c+e.util.getProperty(j);r+=" if ("+z+" === undefined) "+z+" = ",r+="clone"==e.opts.useDefaults?" "+JSON.stringify(V["default"])+" ":" "+e.useDefault(V["default"])+" ",r+="; "}}}else if("array"==T.type&&Array.isArray(e.schema.items)){var U=e.schema.items;if(U)for(var V,$=-1,K=U.length-1;K>$;)if(V=U[$+=1],void 0!==V["default"]){var z=c+"["+$+"]";r+=" if ("+z+" === undefined) "+z+" = ",r+="clone"==e.opts.useDefaults?" "+JSON.stringify(V["default"])+" ":" "+e.useDefault(V["default"])+" ",r+="; "}}var q=T.rules;if(q)for(var G,Y=-1,Q=q.length-1;Q>Y;)if(G=q[Y+=1],n(G)){if(G.custom){var O=e.schema[G.keyword],J=e.useCustomRule(G,O,e.schema,e),X=J.code+".errors",y=e.schemaPath+"."+G.keyword,A=e.errSchemaPath+"/"+G.keyword,Z="errs"+a,$="i"+a,ee="ruleErr"+a,te=G.definition,ie=te.async,ne=te.inline,re=te.macro;if(ie&&!e.async)throw new Error("async keyword in sync schema");if(ne||re||(r+=""+X+" = null;"),r+="var "+Z+" = errors;var valid"+a+";",ne&&te.statements)r+=" "+J.validate;else if(re){var oe=e.util.copy(e);oe.level++,oe.schema=J.validate,oe.schemaPath="";var se=e.compositeRule;e.compositeRule=oe.compositeRule=!0;var ae=e.validate(oe).replace(/validate\.schema/g,J.code);e.compositeRule=oe.compositeRule=se,r+=" "+ae}else if(te.compile||te.validate){var k=k||[];k.push(r),r="",r+=" "+J.code+".call( ",r+=e.opts.passContext?"this":"self";J.validate.length;r+=te.compile||te.schema===!1?" , "+c+" ":" , validate.schema"+y+" , "+c+" , validate.schema"+e.schemaPath+" ",r+=" , (dataPath || '')",'""'!=e.errorPath&&(r+=" + "+e.errorPath),r+=l?" , data"+(l-1||"")+" , "+e.dataPathArr[l]+" ":" , parentData , parentDataProperty ",r+=" ) ";var le=r;r=k.pop(),te.errors!==!1&&(ie?(X="customErrors"+a,r+=" var "+X+" = null; try { valid"+a+" = "+e.yieldAwait+le+"; } catch (e) { valid"+a+" = false; if (e instanceof ValidationError) "+X+" = e.errors; else throw e; } "):r+=" "+J.code+".errors = null; ")}r+="if (! ",r+=ne?te.statements?" valid"+a+" ":" ("+J.validate+") ":re?" valid"+oe.level+" ":ie?te.errors===!1?" ("+e.yieldAwait+le+") ":" valid"+a+" ":" "+le+" ",r+=") { ",d=G.keyword;var k=k||[];k.push(r),r="";var k=k||[];k.push(r),r="",e.createErrors!==!1?(r+=" { keyword: '"+(d||"custom")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+A+"\" , params: { keyword: '"+G.keyword+"' } ",e.opts.messages!==!1&&(r+=" , message: 'should pass \""+G.keyword+"\" keyword validation' "),e.opts.verbose&&(r+=" , schema: validate.schema"+y+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+c+" "),r+=" } "):r+=" {} ";var B=r;r=k.pop(),r+=!e.compositeRule&&f?e.async?" throw new ValidationError(["+B+"]); ":" validate.errors = ["+B+"]; return false; ":" var err = "+B+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ";var ce=r;r=k.pop(),ne?te.errors?"full"!=te.errors&&(r+=" for (var "+$+"="+Z+"; "+$+"2&&(t=d.call(arguments,1)),void i(t))})})}function o(e){return Promise.all(e.map(n,this))}function s(e){function t(e,t){i[t]=void 0,o.push(e.then(function(e){i[t]=e}))}for(var i=new e.constructor,r=Object.keys(e),o=[],s=0;s=1&&12>=i&&n>=1&&n<=m[i]}function o(e,t){var i=e.match(g);if(!i)return!1;var n=i[1],r=i[2],o=i[3],s=i[5];return 23>=n&&59>=r&&59>=o&&(!t||s)}function s(e){var t=e.split(E);return r(t[0])&&o(t[1],!0)}function a(e){return e.length<=255&&v.test(e)}function l(e){return b.test(e)&&w.test(e)}function c(e){try{return new RegExp(e),!0}catch(t){return!1}}function h(e,t){return e&&t?e>t?1:t>e?-1:e===t?0:void 0:void 0}function d(e,t){return e&&t&&(e=e.match(g),t=t.match(g),e&&t)?(e=e[1]+e[2]+e[3]+(e[4]||""),t=t[1]+t[2]+t[3]+(t[4]||""),e>t?1:t>e?-1:e===t?0:void 0):void 0}function u(e,t){if(e&&t){e=e.split(E),t=t.split(E);var i=h(e[0],t[0]);if(void 0!==i)return i||d(e[1],t[1])}}var f=i(11),p=/^\d\d\d\d-(\d\d)-(\d\d)$/,m=[0,31,29,31,30,31,30,31,31,30,31,30,31],g=/^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i,v=/^[a-z](?:(?:[-0-9a-z]{0,61})?[0-9a-z])?(\.[a-z](?:(?:[-0-9a-z]{0,61})?[0-9a-z])?)*$/i,w=/^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?$/i,y=/^(?:urn\:uuid\:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,A=/^(?:\/(?:[^~\/]|~0|~1)+)*(?:\/)?$|^\#(?:\/(?:[a-z0-9_\-\.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)+)*(?:\/)?$/i,C=/^(?:0|[1-9][0-9]*)(?:\#|(?:\/(?:[^~\/]|~0|~1)+)*(?:\/)?)$/;e.exports=n,n.fast={date:/^\d\d\d\d-[0-1]\d-[0-3]\d$/,time:/^[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i,"date-time":/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s][0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i,uri:/^(?:[a-z][a-z0-9+-.]*)?(?:\:|\/)\/?[^\s]*$/i,email:/^[a-z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,hostname:v,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:c,uuid:y,"json-pointer":A,"relative-json-pointer":C},n.full={date:r,time:o,"date-time":s,uri:l,email:/^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&''*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,hostname:a,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:c,uuid:y,"json-pointer":A,"relative-json-pointer":C},n.compare={date:h,time:d,"date-time":u};var E=/t|\s/i,b=/\/|\:/},function(e,t,i){"use strict";var n=i(24),r=i(11);e.exports=function(){var e=[{type:"number",rules:["maximum","minimum","multipleOf"]},{type:"string",rules:["maxLength","minLength","pattern","format"]},{type:"array",rules:["maxItems","minItems","uniqueItems","items"]},{type:"object",rules:["maxProperties","minProperties","required","dependencies","properties"]},{rules:["$ref","enum","not","anyOf","oneOf","allOf"]}];return e.all=["type","additionalProperties","patternProperties"],e.keywords=["additionalItems","$schema","id","title","description","default"],e.types=["number","integer","string","array","object","boolean","null"],e.forEach(function(t){t.rules=t.rules.map(function(t){return e.all.push(t),{keyword:t,code:n[t]}})}),e.keywords=r.toHash(e.all.concat(e.keywords)),e.all=r.toHash(e.all),e.types=r.toHash(e.types),e}},function(e,t,i){"use strict";e.exports={$ref:i(25),allOf:i(26),anyOf:i(27),dependencies:i(28),"enum":i(29),format:i(30),items:i(31),maximum:i(32),minimum:i(32),maxItems:i(33),minItems:i(33),maxLength:i(34),minLength:i(34),maxProperties:i(35),minProperties:i(35),multipleOf:i(36),not:i(37),oneOf:i(38),pattern:i(39),properties:i(40),required:i(41),uniqueItems:i(42),validate:i(18)}},function(e,t){"use strict";e.exports=function(e,t){var i,n,r,o=" ",s=e.level,a=e.dataLevel,l=e.schema[t],c=e.errSchemaPath+"/"+t,h=!e.opts.allErrors,d="data"+(a||""),u="valid"+s;if("#"==l||"#/"==l)e.isRoot?(n=e.async,r="validate"):(n=e.root.schema.$async===!0,r="root.refVal[0]");else{var f=e.resolveRef(e.baseId,l,e.isRoot);if(void 0===f){var p="can't resolve reference "+l+" from id "+e.baseId;if("fail"==e.opts.missingRefs){console.log(p);var m=m||[];m.push(o),o="",e.createErrors!==!1?(o+=" { keyword: '"+(i||"$ref")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+c+"\" , params: { ref: '"+e.util.escapeQuotes(l)+"' } ",e.opts.messages!==!1&&(o+=" , message: 'can\\'t resolve reference "+e.util.escapeQuotes(l)+"' "),e.opts.verbose&&(o+=" , schema: "+e.util.toQuotedString(l)+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+d+" "),o+=" } "):o+=" {} ";var g=o;o=m.pop(),o+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+g+"]); ":" validate.errors = ["+g+"]; return false; ":" var err = "+g+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",h&&(o+=" if (false) { ")}else{if("ignore"!=e.opts.missingRefs){var v=new Error(p);throw v.missingRef=e.resolve.url(e.baseId,l),v.missingSchema=e.resolve.normalizeId(e.resolve.fullPath(v.missingRef)),v}console.log(p),h&&(o+=" if (true) { ")}}else if(f.inline){var w=e.util.copy(e);w.level++,w.schema=f.schema,w.schemaPath="",w.errSchemaPath=l;var y=e.validate(w).replace(/validate\.schema/g,f.code);o+=" "+y+" ",h&&(o+=" if (valid"+w.level+") { ")}else n=f.async,r=f.code}if(r){var m=m||[];m.push(o),o="",o+=e.opts.passContext?" "+r+".call(this, ":" "+r+"( ",o+=" "+d+", (dataPath || '')",'""'!=e.errorPath&&(o+=" + "+e.errorPath),o+=a?" , data"+(a-1||"")+" , "+e.dataPathArr[a]+" ":" , parentData , parentDataProperty ",o+=") ";var A=o;if(o=m.pop(),n){if(!e.async)throw new Error("async schema referenced by sync schema");o+=" try { ",h&&(o+="var "+u+" ="),o+=" "+e.yieldAwait+" "+A+"; } catch (e) { if (!(e instanceof ValidationError)) throw e; if (vErrors === null) vErrors = e.errors; else vErrors = vErrors.concat(e.errors); errors = vErrors.length; } ",h&&(o+=" if ("+u+") { ")}else o+=" if (!"+A+") { if (vErrors === null) vErrors = "+r+".errors; else vErrors = vErrors.concat("+r+".errors); errors = vErrors.length; } ",h&&(o+=" else { ")}return o}},function(e,t){"use strict";e.exports=function(e,t){var i=" ",n=e.schema[t],r=e.schemaPath+"."+t,o=e.errSchemaPath+"/"+t,s=!e.opts.allErrors,a=e.util.copy(e),l="";a.level++;var c=n;if(c)for(var h,d=-1,u=c.length-1;u>d;)h=c[d+=1],e.util.schemaHasRules(h,e.RULES.all)&&(a.schema=h,a.schemaPath=r+"["+d+"]",a.errSchemaPath=o+"/"+d,i+=" "+e.validate(a)+" ",s&&(i+=" if (valid"+a.level+") { ",l+="}"));return s&&(i+=" "+l.slice(0,-1)),i=e.util.cleanUpCode(i)}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="errs__"+r,f=e.util.copy(e),p="";f.level++;var m=s.every(function(t){return e.util.schemaHasRules(t,e.RULES.all)});if(m){n+=" var "+u+" = errors; var "+d+" = false; ";var g=e.compositeRule;e.compositeRule=f.compositeRule=!0;var v=s;if(v)for(var w,y=-1,A=v.length-1;A>y;)w=v[y+=1],f.schema=w,f.schemaPath=a+"["+y+"]",f.errSchemaPath=l+"/"+y,n+=" "+e.validate(f)+" "+d+" = "+d+" || valid"+f.level+"; if (!"+d+") { ",p+="}";e.compositeRule=f.compositeRule=g,n+=" "+p+" if (!"+d+") { var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"anyOf")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should match some schema in anyOf' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else { errors = "+u+"; if (vErrors !== null) { if ("+u+") vErrors.length = "+u+"; else vErrors = null; } ",e.opts.allErrors&&(n+=" } "),n=e.util.cleanUpCode(n)}else c&&(n+=" if (true) { ");return n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="errs__"+r,u=e.util.copy(e),f="";u.level++;var p={},m={};for(y in s){var g=s[y],v=Array.isArray(g)?m:p;v[y]=g}n+="var "+d+" = errors;";var w=e.errorPath;n+="var missing"+r+";";for(var y in m){v=m[y],n+=" if ("+h+e.util.getProperty(y)+" !== undefined && ( ";var A=v;if(A)for(var C,E=-1,b=A.length-1;b>E;){C=A[E+=1],E&&(n+=" || ");var F=e.util.getProperty(C);n+=" ( "+h+F+" === undefined && (missing"+r+" = "+e.util.toQuotedString(e.opts.jsonPointers?C:F)+") ) "}n+=")) { ";var x="missing"+r,S="' + "+x+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.opts.jsonPointers?e.util.getPathExpr(w,x,!0):w+" + "+x);var $=$||[];$.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"dependencies")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { property: '"+e.util.escapeQuotes(y)+"', missingProperty: '"+S+"', depsCount: "+v.length+", deps: '"+e.util.escapeQuotes(1==v.length?v[0]:v.join(", "))+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should have ",n+=1==v.length?"property "+e.util.escapeQuotes(v[0]):"properties "+e.util.escapeQuotes(v.join(", ")),n+=" when property "+e.util.escapeQuotes(y)+" is present' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var D=n;n=$.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+D+"]); ":" validate.errors = ["+D+"]; return false; ":" var err = "+D+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",c&&(f+="}",n+=" else { ")}e.errorPath=w;for(var y in p){var g=p[y];e.util.schemaHasRules(g,e.RULES.all)&&(n+=" valid"+u.level+" = true; if ("+h+"['"+y+"'] !== undefined) { ",u.schema=g,u.schemaPath=a+e.util.getProperty(y),u.errSchemaPath=l+"/"+e.util.escapeFragment(y),n+=" "+e.validate(u)+" } ",c&&(n+=" if (valid"+u.level+") { ",f+="}"))}return c&&(n+=" "+f+" if ("+d+" == errors) {"),n=e.util.cleanUpCode(n)}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u=e.opts.v5&&s.$data,f=u?e.util.getData(s.$data,o,e.dataPathArr):s; +u&&(n+=" var schema"+r+" = "+f+"; ",f="schema"+r);var p="i"+r;u||(n+=" var schema"+r+" = validate.schema"+a+";"),n+="var "+d+";",u&&(n+=" if (schema"+r+" === undefined) "+d+" = true; else if (!Array.isArray(schema"+r+")) "+d+" = false; else {"),n+=""+d+" = false;for (var "+p+"=0; "+p+"b;)if(E=C[b+=1],e.util.schemaHasRules(E,e.RULES.all)){n+=" valid"+f.level+" = true; if ("+h+".length > "+b+") { ";var x=h+"["+b+"]";f.schema=E,f.schemaPath=a+"["+b+"]",f.errSchemaPath=l+"/"+b,f.errorPath=e.util.getPathExpr(e.errorPath,b,e.opts.jsonPointers,!0),f.dataPathArr[m]=b;var S=e.validate(f);n+=e.util.varOccurences(S,g)<2?" "+e.util.varReplace(S,g,x)+" ":" var "+g+" = "+x+"; "+S+" ",n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}if("object"==typeof v&&e.util.schemaHasRules(v,e.RULES.all)){f.schema=v,f.schemaPath=e.schemaPath+".additionalItems",f.errSchemaPath=e.errSchemaPath+"/additionalItems",n+=" valid"+f.level+" = true; if ("+h+".length > "+s.length+") { for (var i"+r+" = "+s.length+"; i"+r+" < "+h+".length; i"+r+"++) { ",f.errorPath=e.util.getPathExpr(e.errorPath,"i"+r,e.opts.jsonPointers,!0);var x=h+"[i"+r+"]";f.dataPathArr[m]="i"+r;var S=e.validate(f);n+=e.util.varOccurences(S,g)<2?" "+e.util.varReplace(S,g,x)+" ":" var "+g+" = "+x+"; "+S+" ",c&&(n+=" if (!valid"+f.level+") break; "),n+=" } } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}}else if(e.util.schemaHasRules(s,e.RULES.all)){f.schema=s,f.schemaPath=a,f.errSchemaPath=l,n+=" for (var i"+r+" = 0; i"+r+" < "+h+".length; i"+r+"++) { ",f.errorPath=e.util.getPathExpr(e.errorPath,"i"+r,e.opts.jsonPointers,!0);var x=h+"[i"+r+"]";f.dataPathArr[m]="i"+r;var S=e.validate(f);n+=e.util.varOccurences(S,g)<2?" "+e.util.varReplace(S,g,x)+" ":" var "+g+" = "+x+"; "+S+" ",c&&(n+=" if (!valid"+f.level+") break; "),n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}return c&&(n+=" "+p+" if ("+u+" == errors) {"),n=e.util.cleanUpCode(n)}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f="maximum"==t,p=f?"exclusiveMaximum":"exclusiveMinimum",m=e.schema[p],g=e.opts.v5&&m&&m.$data,v=f?"<":">",w=f?">":"<";if(g){var y=e.util.getData(m.$data,o,e.dataPathArr),A="exclusive"+r,C="op"+r,E="' + "+C+" + '";n+=" var schemaExcl"+r+" = "+y+"; ",y="schemaExcl"+r,n+=" var exclusive"+r+"; if (typeof "+y+" != 'boolean' && typeof "+y+" != 'undefined') { ";var i=p,b=b||[];b.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_exclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: '"+p+" should be boolean' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var F=n;n=b.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+F+"]); ":" validate.errors = ["+F+"]; return false; ":" var err = "+F+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } else if( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=" ((exclusive"+r+" = "+y+" === true) ? "+h+" "+w+"= "+u+" : "+h+" "+w+" "+u+")) { var op"+r+" = exclusive"+r+" ? '"+v+"' : '"+v+"=';"}else{var A=m===!0,E=v;A||(E+="=");var C="'"+E+"'";n+=" if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=" "+h+" "+w,A&&(n+="="),n+=" "+u+") {"}var i=t,b=b||[];b.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_limit")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { comparison: '+C+", limit: "+u+", exclusive: "+A+" } ",e.opts.messages!==!1&&(n+=" , message: 'should be "+E+" ",n+=d?"' + "+u:""+s+"'"),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var F=n;return n=b.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+F+"]); ":" validate.errors = ["+F+"]; return false; ":" var err = "+F+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",c&&(n+=" else { "),n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f="maxItems"==t?">":"<";n+="if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=" "+h+".length "+f+" "+u+") { ";var i=t,p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_limitItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { limit: '+u+" } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have ",n+="maxItems"==t?"more":"less",n+=" than ",n+=d?"' + "+u+" + '":""+s,n+=" items' "),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var m=n;return n=p.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f="maxLength"==t?">":"<";n+="if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=e.opts.unicode===!1?" "+h+".length ":" ucs2length("+h+") ",n+=" "+f+" "+u+") { ";var i=t,p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_limitLength")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { limit: '+u+" } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT be ",n+="maxLength"==t?"longer":"shorter",n+=" than ",n+=d?"' + "+u+" + '":""+s,n+=" characters' "),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var m=n;return n=p.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f="maxProperties"==t?">":"<";n+="if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'number') || "),n+=" Object.keys("+h+").length "+f+" "+u+") { ";var i=t,p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_limitProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { limit: '+u+" } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have ",n+="maxProperties"==t?"more":"less",n+=" than ",n+=d?"' + "+u+" + '":""+s,n+=" properties' "),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var m=n;return n=p.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r),n+="var division"+r+";if (",d&&(n+=" "+u+" !== undefined && ( typeof "+u+" != 'number' || "),n+=" (division"+r+" = "+h+" / "+u+", ",n+=e.opts.multipleOfPrecision?" Math.abs(Math.round(division"+r+") - division"+r+") > 1e-"+e.opts.multipleOfPrecision+" ":" division"+r+" !== parseInt(division"+r+") ",n+=" ) ",d&&(n+=" ) "),n+=" ) { ";var f=f||[];f.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"multipleOf")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { multipleOf: '+u+" } ",e.opts.messages!==!1&&(n+=" , message: 'should be multiple of ",n+=d?"' + "+u:""+s+"'"),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var p=n;return n=f.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="errs__"+r,u=e.util.copy(e);if(u.level++,e.util.schemaHasRules(s,e.RULES.all)){u.schema=s,u.schemaPath=a,u.errSchemaPath=l,n+=" var "+d+" = errors; ";var f=e.compositeRule;e.compositeRule=u.compositeRule=!0,u.createErrors=!1;var p;u.opts.allErrors&&(p=u.opts.allErrors,u.opts.allErrors=!1),n+=" "+e.validate(u)+" ",u.createErrors=!0,p&&(u.opts.allErrors=p),e.compositeRule=u.compositeRule=f,n+=" if (valid"+u.level+") { ";var m=m||[];m.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"not")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should NOT be valid' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var g=n;n=m.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+g+"]); ":" validate.errors = ["+g+"]; return false; ":" var err = "+g+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } else { errors = "+d+"; if (vErrors !== null) { if ("+d+") vErrors.length = "+d+"; else vErrors = null; } ",e.opts.allErrors&&(n+=" } ")}else n+=" var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"not")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should NOT be valid' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",c&&(n+=" if (false) { ");return n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="errs__"+r,f=e.util.copy(e),p="";f.level++,n+="var "+u+" = errors;var prevValid"+r+" = false;var "+d+" = false; ";var m=e.compositeRule;e.compositeRule=f.compositeRule=!0;var g=s;if(g)for(var v,w=-1,y=g.length-1;y>w;)v=g[w+=1],e.util.schemaHasRules(v,e.RULES.all)?(f.schema=v,f.schemaPath=a+"["+w+"]",f.errSchemaPath=l+"/"+w,n+=" "+e.validate(f)+" "):n+=" var valid"+f.level+" = true; ",w&&(n+=" if (valid"+f.level+" && prevValid"+r+") "+d+" = false; else { ",p+="}"),n+=" if (valid"+f.level+") "+d+" = prevValid"+r+" = true;";e.compositeRule=f.compositeRule=m,n+=""+p+"if (!"+d+") { ";var A=A||[];A.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"oneOf")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should match exactly one schema in oneOf' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var C=n;return n=A.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+C+"]); ":" validate.errors = ["+C+"]; return false; ":" var err = "+C+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} else { errors = "+u+"; if (vErrors !== null) { if ("+u+") vErrors.length = "+u+"; else vErrors = null; }",e.opts.allErrors&&(n+=" } "),n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d=e.opts.v5&&s.$data,u=d?e.util.getData(s.$data,o,e.dataPathArr):s;d&&(n+=" var schema"+r+" = "+u+"; ",u="schema"+r);var f=d?"(new RegExp("+u+"))":e.usePattern(s);n+="if ( ",d&&(n+=" ("+u+" !== undefined && typeof "+u+" != 'string') || "),n+=" !"+f+".test("+h+") ) { ";var p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"pattern")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { pattern: ',n+=d?""+u:""+e.util.toQuotedString(s),n+=" } ",e.opts.messages!==!1&&(n+=" , message: 'should match pattern \"",n+=d?"' + "+u+" + '":""+e.util.escapeQuotes(s),n+="\"' "),e.opts.verbose&&(n+=" , schema: ",n+=d?"validate.schema"+a:""+e.util.toQuotedString(s),n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var m=n;return n=p.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="} ",c&&(n+=" else { "),n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="errs__"+r,f=e.util.copy(e),p="";f.level++;var m=f.dataLevel=e.dataLevel+1,g="data"+m,v=Object.keys(s||{}),w=e.schema.patternProperties||{},y=Object.keys(w),A=e.schema.additionalProperties,C=v.length||y.length,E=A===!1,b="object"==typeof A&&Object.keys(A).length,F=e.opts.removeAdditional,x=E||b||F,S=e.schema.required;if(S&&(!e.opts.v5||!S.$data)&&S.length5)n+=" || validate.schema"+a+"[key"+r+"] ";else{var B=v;if(B)for(var _,L=-1,R=B.length-1;R>L;)_=B[L+=1],n+=" || key"+r+" == "+e.util.toQuotedString(_)+" "}if(y.length){var T=y;if(T)for(var P,M=-1,O=T.length-1;O>M;)P=T[M+=1],n+=" || "+e.usePattern(P)+".test(key"+r+") "}if(e.opts.v5&&k&&k.length){var N=k;if(N)for(var I,M=-1,j=N.length-1;j>M;)I=N[M+=1],n+=" || "+e.usePattern(I)+".test(key"+r+") "}n+=" ); if (isAdditional"+r+") { "}if("all"==F)n+=" delete "+h+"[key"+r+"]; ";else{var W=e.errorPath,H="' + key"+r+" + '";if(e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers)),E)if(F)n+=" delete "+h+"[key"+r+"]; ";else{n+=" valid"+f.level+" = false; ";var V=l;l=e.errSchemaPath+"/additionalProperties";var z=z||[];z.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"additionalProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { additionalProperty: '"+H+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have additional properties' "),e.opts.verbose&&(n+=" , schema: false , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var U=n;n=z.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+U+"]); ":" validate.errors = ["+U+"]; return false; ":" var err = "+U+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",l=V,c&&(n+=" break; ")}else if(b)if("failing"==F){n+=" var "+u+" = errors; ";var K=e.compositeRule;e.compositeRule=f.compositeRule=!0,f.schema=A,f.schemaPath=e.schemaPath+".additionalProperties",f.errSchemaPath=e.errSchemaPath+"/additionalProperties",f.errorPath=e.opts._errorDataPathProperty?e.errorPath:e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers);var q=h+"[key"+r+"]";f.dataPathArr[m]="key"+r;var G=e.validate(f);n+=e.util.varOccurences(G,g)<2?" "+e.util.varReplace(G,g,q)+" ":" var "+g+" = "+q+"; "+G+" ",n+=" if (!valid"+f.level+") { errors = "+u+"; if (validate.errors !== null) { if (errors) validate.errors.length = errors; else validate.errors = null; } delete "+h+"[key"+r+"]; } ",e.compositeRule=f.compositeRule=K}else{f.schema=A,f.schemaPath=e.schemaPath+".additionalProperties",f.errSchemaPath=e.errSchemaPath+"/additionalProperties",f.errorPath=e.opts._errorDataPathProperty?e.errorPath:e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers);var q=h+"[key"+r+"]";f.dataPathArr[m]="key"+r;var G=e.validate(f);n+=e.util.varOccurences(G,g)<2?" "+e.util.varReplace(G,g,q)+" ":" var "+g+" = "+q+"; "+G+" ",c&&(n+=" if (!valid"+f.level+") break; ")}e.errorPath=W}C&&(n+=" } "),n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}var Y=e.opts.useDefaults&&!e.compositeRule;if(v.length){var Q=v;if(Q)for(var _,J=-1,X=Q.length-1;X>J;){_=Q[J+=1];var Z=s[_];if(e.util.schemaHasRules(Z,e.RULES.all)){var ee=e.util.getProperty(_),q=h+ee,te=Y&&void 0!==Z["default"];f.schema=Z,f.schemaPath=a+ee,f.errSchemaPath=l+"/"+e.util.escapeFragment(_),f.errorPath=e.util.getPath(e.errorPath,_,e.opts.jsonPointers),f.dataPathArr[m]=e.util.toQuotedString(_);var G=e.validate(f);if(e.util.varOccurences(G,g)<2){G=e.util.varReplace(G,g,q);var ie=q}else{var ie=g;n+=" var "+g+" = "+q+"; "}if(te)n+=" "+G+" ";else{if($&&$[_]){n+=" if ("+ie+" === undefined) { valid"+f.level+" = false; ";var W=e.errorPath,V=l,ne=e.util.escapeQuotes(_);e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPath(W,_,e.opts.jsonPointers)),l=e.errSchemaPath+"/required";var z=z||[];z.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+ne+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+ne+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var U=n;n=z.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+U+"]); ":" validate.errors = ["+U+"]; return false; ":" var err = "+U+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",l=V,e.errorPath=W,n+=" } else { "}else n+=c?" if ("+ie+" === undefined) { valid"+f.level+" = true; } else { ":" if ("+ie+" !== undefined) { ";n+=" "+G+" } "}}c&&(n+=" if (valid"+f.level+") { ",p+="}")}}var re=y;if(re)for(var P,oe=-1,se=re.length-1;se>oe;){P=re[oe+=1];var Z=w[P];if(e.util.schemaHasRules(Z,e.RULES.all)){f.schema=Z,f.schemaPath=e.schemaPath+".patternProperties"+e.util.getProperty(P),f.errSchemaPath=e.errSchemaPath+"/patternProperties/"+e.util.escapeFragment(P),n+=" for (var key"+r+" in "+h+") { if ("+e.usePattern(P)+".test(key"+r+")) { ",f.errorPath=e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers);var q=h+"[key"+r+"]";f.dataPathArr[m]="key"+r;var G=e.validate(f);n+=e.util.varOccurences(G,g)<2?" "+e.util.varReplace(G,g,q)+" ":" var "+g+" = "+q+"; "+G+" ",c&&(n+=" if (!valid"+f.level+") break; "),n+=" } ",c&&(n+=" else valid"+f.level+" = true; "),n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}")}}if(e.opts.v5){var ae=k;if(ae)for(var I,le=-1,ce=ae.length-1;ce>le;){I=ae[le+=1];var he=D[I],Z=he.schema;if(e.util.schemaHasRules(Z,e.RULES.all)){f.schema=Z,f.schemaPath=e.schemaPath+".patternGroups"+e.util.getProperty(I)+".schema",f.errSchemaPath=e.errSchemaPath+"/patternGroups/"+e.util.escapeFragment(I)+"/schema",n+=" var pgPropCount"+r+" = 0; for (var key"+r+" in "+h+") { if ("+e.usePattern(I)+".test(key"+r+")) { pgPropCount"+r+"++; ",f.errorPath=e.util.getPathExpr(e.errorPath,"key"+r,e.opts.jsonPointers);var q=h+"[key"+r+"]";f.dataPathArr[m]="key"+r;var G=e.validate(f);n+=e.util.varOccurences(G,g)<2?" "+e.util.varReplace(G,g,q)+" ":" var "+g+" = "+q+"; "+G+" ",c&&(n+=" if (!valid"+f.level+") break; "),n+=" } ",c&&(n+=" else valid"+f.level+" = true; "),n+=" } ",c&&(n+=" if (valid"+f.level+") { ",p+="}");var de=he.minimum,ue=he.maximum;if(void 0!==de||void 0!==ue){n+=" var "+d+" = true; ";var V=l;if(void 0!==de){var fe=de,pe="minimum",me="less";n+=" "+d+" = pgPropCount"+r+" >= "+de+"; ",l=e.errSchemaPath+"/patternGroups/minimum",n+=" if (!"+d+") { ";var z=z||[];z.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"patternGroups")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { reason: '"+pe+"', limit: "+fe+", pattern: '"+e.util.escapeQuotes(I)+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have "+me+" than "+fe+' properties matching pattern "'+e.util.escapeQuotes(I)+"\"' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var U=n;n=z.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+U+"]); ":" validate.errors = ["+U+"]; return false; ":" var err = "+U+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",void 0!==ue&&(n+=" else ")}if(void 0!==ue){var fe=ue,pe="maximum",me="more";n+=" "+d+" = pgPropCount"+r+" <= "+ue+"; ",l=e.errSchemaPath+"/patternGroups/maximum",n+=" if (!"+d+") { ";var z=z||[];z.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"patternGroups")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { reason: '"+pe+"', limit: "+fe+", pattern: '"+e.util.escapeQuotes(I)+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should NOT have "+me+" than "+fe+' properties matching pattern "'+e.util.escapeQuotes(I)+"\"' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var U=n;n=z.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+U+"]); ":" validate.errors = ["+U+"]; return false; ":" var err = "+U+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } "}l=V,c&&(n+=" if ("+d+") { ",p+="}")}}}}return c&&(n+=" "+p+" if ("+u+" == errors) {"),n=e.util.cleanUpCode(n)}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u=e.opts.v5&&s.$data,f=u?e.util.getData(s.$data,o,e.dataPathArr):s;if(u&&(n+=" var schema"+r+" = "+f+"; ",f="schema"+r),!u)if(s.lengthv;){g=m[v+=1];var y=e.schema.properties[g];y&&e.util.schemaHasRules(y,e.RULES.all)||(p[p.length]=g)}}else var p=s;if(u||p.length){var A=e.errorPath,C=u||p.length>=e.opts.loopRequired;if(c)if(n+=" var missing"+r+"; ",C){u||(n+=" var schema"+r+" = validate.schema"+a+"; ");var E="i"+r,b="schema"+r+"["+E+"]",F="' + "+b+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(A,b,e.opts.jsonPointers)),n+=" var "+d+" = true; ",u&&(n+=" if (schema"+r+" === undefined) "+d+" = true; else if (!Array.isArray(schema"+r+")) "+d+" = false; else {"),n+=" for (var "+E+" = 0; "+E+" < schema"+r+".length; "+E+"++) { "+d+" = "+h+"[schema"+r+"["+E+"]] !== undefined; if (!"+d+") break; } ",u&&(n+=" } "),n+=" if (!"+d+") { ";var x=x||[];x.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var S=n;n=x.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+S+"]); ":" validate.errors = ["+S+"]; return false; ":" var err = "+S+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } else { "}else{n+=" if ( ";var $=p;if($)for(var D,E=-1,k=$.length-1;k>E;){D=$[E+=1],E&&(n+=" || ");var B=e.util.getProperty(D);n+=" ( "+h+B+" === undefined && (missing"+r+" = "+e.util.toQuotedString(e.opts.jsonPointers?D:B)+") ) "}n+=") { ";var b="missing"+r,F="' + "+b+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.opts.jsonPointers?e.util.getPathExpr(A,b,!0):A+" + "+b);var x=x||[];x.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var S=n;n=x.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+S+"]); ":" validate.errors = ["+S+"]; return false; ":" var err = "+S+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } else { "}else if(C){u||(n+=" var schema"+r+" = validate.schema"+a+"; ");var E="i"+r,b="schema"+r+"["+E+"]",F="' + "+b+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(A,b,e.opts.jsonPointers)),u&&(n+=" if (schema"+r+" && !Array.isArray(schema"+r+")) { var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else if (schema"+r+" !== undefined) { "),n+=" for (var "+E+" = 0; "+E+" < schema"+r+".length; "+E+"++) { if ("+h+"[schema"+r+"["+E+"]] === undefined) { var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'",n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } } ",u&&(n+=" } ")}else{var _=p;if(_)for(var g,E=-1,L=_.length-1;L>E;){g=_[E+=1];var B=e.util.getProperty(g),F=e.util.escapeQuotes(g);e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPath(A,g,e.opts.jsonPointers)),n+=" if ("+h+B+" === undefined) { var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingProperty: '"+F+"' } ",e.opts.messages!==!1&&(n+=" , message: '",n+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+F+"\\'", +n+="' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } "}}e.errorPath=A}else c&&(n+=" if (true) {");return n}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u=e.opts.v5&&s.$data,f=u?e.util.getData(s.$data,o,e.dataPathArr):s;if(u&&(n+=" var schema"+r+" = "+f+"; ",f="schema"+r),(s||u)&&e.opts.uniqueItems!==!1){u&&(n+=" var "+d+"; if ("+f+" === false || "+f+" === undefined) "+d+" = true; else if (typeof "+f+" != 'boolean') "+d+" = false; else { "),n+=" var "+d+" = true; if ("+h+".length > 1) { var i = "+h+".length, j; outer: for (;i--;) { for (j = i; j--;) { if (equal("+h+"[i], "+h+"[j])) { "+d+" = false; break outer; } } } } ",u&&(n+=" } "),n+=" if (!"+d+") { ";var p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"uniqueItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { i: i, j: j } ',e.opts.messages!==!1&&(n+=" , message: 'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)' "),e.opts.verbose&&(n+=" , schema: ",n+=u?"validate.schema"+a:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var m=n;n=p.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",c&&(n+=" else { ")}else c&&(n+=" if (true) { ");return n}},function(e,t,i){"use strict";function n(e){function t(t,i,r){var o={inline:r||n[t],statements:!0,errors:"full"};i&&(o.type=i),e.addKeyword(t,o)}var n={"switch":i(44),constant:i(45),_formatLimit:i(46),patternRequired:i(47)};if(e._opts.meta!==!1){var s=i(48);e.addMetaSchema(s,o)}t("constant"),e.addKeyword("contains",{type:"array",macro:r}),t("formatMaximum","string",n._formatLimit),t("formatMinimum","string",n._formatLimit),e.addKeyword("exclusiveFormatMaximum"),e.addKeyword("exclusiveFormatMinimum"),e.addKeyword("patternGroups"),t("patternRequired","object"),t("switch")}function r(e){return{not:{items:{not:e}}}}var o="https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json";e.exports={enable:n,META_SCHEMA_ID:o}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="errs__"+r,f=e.util.copy(e),p="";f.level++;var m,g="ifPassed"+e.level;n+="var "+g+";";var v=s;if(v)for(var w,y=-1,A=v.length-1;A>y;){if(w=v[y+=1],y&&!m&&(n+=" if (!"+g+") { ",p+="}"),w["if"]&&e.util.schemaHasRules(w["if"],e.RULES.all)){n+=" var "+u+" = errors; ";var C=e.compositeRule;if(e.compositeRule=f.compositeRule=!0,f.createErrors=!1,f.schema=w["if"],f.schemaPath=a+"["+y+"].if",f.errSchemaPath=l+"/"+y+"/if",n+=" "+e.validate(f)+" ",f.createErrors=!0,e.compositeRule=f.compositeRule=C,n+=" "+g+" = valid"+f.level+"; if ("+g+") { ","boolean"==typeof w.then){if(w.then===!1){var E=E||[];E.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"switch")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { caseIndex: '+y+" } ",e.opts.messages!==!1&&(n+=" , message: 'should pass \"switch\" keyword validation' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var b=n;n=E.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+b+"]); ":" validate.errors = ["+b+"]; return false; ":" var err = "+b+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; "}n+=" var valid"+f.level+" = "+w.then+"; "}else f.schema=w.then,f.schemaPath=a+"["+y+"].then",f.errSchemaPath=l+"/"+y+"/then",n+=" "+e.validate(f)+" ";n+=" } else { errors = "+u+"; if (vErrors !== null) { if ("+u+") vErrors.length = "+u+"; else vErrors = null; } } "}else if(n+=" "+g+" = true; ","boolean"==typeof w.then){if(w.then===!1){var E=E||[];E.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"switch")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { caseIndex: '+y+" } ",e.opts.messages!==!1&&(n+=" , message: 'should pass \"switch\" keyword validation' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var b=n;n=E.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+b+"]); ":" validate.errors = ["+b+"]; return false; ":" var err = "+b+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; "}n+=" var valid"+f.level+" = "+w.then+"; "}else f.schema=w.then,f.schemaPath=a+"["+y+"].then",f.errSchemaPath=l+"/"+y+"/then",n+=" "+e.validate(f)+" ";m=w["continue"]}return n+=""+p+"var "+d+" = valid"+f.level+"; ",n=e.util.cleanUpCode(n)}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u=e.opts.v5&&s.$data,f=u?e.util.getData(s.$data,o,e.dataPathArr):s;u&&(n+=" var schema"+r+" = "+f+"; ",f="schema"+r),u||(n+=" var schema"+r+" = validate.schema"+a+";"),n+="var "+d+" = equal("+h+", schema"+r+"); if (!"+d+") { ";var p=p||[];p.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"constant")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: 'should be equal to constant' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var m=n;return n=p.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" }"}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r;if(n+="var "+d+" = undefined;",e.opts.format===!1)return n+=" "+d+" = true; ";var u=e.schema.format,f=e.opts.v5&&u.$data,p="";if(f){var m=e.util.getData(u.$data,o,e.dataPathArr),g="format"+r,v="compare"+r;n+=" var "+g+" = formats["+m+"] , "+v+" = "+g+" && "+g+".compare;"}else{var g=e.formats[u];if(!g||!g.compare)return n+=" "+d+" = true; ";var v="formats"+e.util.getProperty(u)+".compare"}var w="formatMaximum"==t,y="exclusiveFormat"+(w?"Maximum":"Minimum"),A=e.schema[y],C=e.opts.v5&&A&&A.$data,E=w?"<":">",b="result"+r,F=e.opts.v5&&s.$data,x=F?e.util.getData(s.$data,o,e.dataPathArr):s;if(F&&(n+=" var schema"+r+" = "+x+"; ",x="schema"+r),C){var S=e.util.getData(A.$data,o,e.dataPathArr),$="exclusive"+r,D="op"+r,k="' + "+D+" + '";n+=" var schemaExcl"+r+" = "+S+"; ",S="schemaExcl"+r,n+=" if (typeof "+S+" != 'boolean' && "+S+" !== undefined) { "+d+" = false; ";var i=y,B=B||[];B.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_exclusiveFormatLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: {} ',e.opts.messages!==!1&&(n+=" , message: '"+y+" should be boolean' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var _=n;n=B.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+_+"]); ":" validate.errors = ["+_+"]; return false; ":" var err = "+_+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",c&&(p+="}",n+=" else { "),F&&(n+=" if ("+x+" === undefined) "+d+" = true; else if (typeof "+x+" != 'string') "+d+" = false; else { ",p+="}"),f&&(n+=" if (!"+v+") "+d+" = true; else { ",p+="}"),n+=" var "+b+" = "+v+"("+h+", ",n+=F?""+x:""+e.util.toQuotedString(s),n+=" ); if ("+b+" === undefined) "+d+" = false; var exclusive"+r+" = "+S+" === true; if ("+d+" === undefined) { "+d+" = exclusive"+r+" ? "+b+" "+E+" 0 : "+b+" "+E+"= 0; } if (!"+d+") var op"+r+" = exclusive"+r+" ? '"+E+"' : '"+E+"=';"}else{var $=A===!0,k=E;$||(k+="=");var D="'"+k+"'";F&&(n+=" if ("+x+" === undefined) "+d+" = true; else if (typeof "+x+" != 'string') "+d+" = false; else { ",p+="}"),f&&(n+=" if (!"+v+") "+d+" = true; else { ",p+="}"),n+=" var "+b+" = "+v+"("+h+", ",n+=F?""+x:""+e.util.toQuotedString(s),n+=" ); if ("+b+" === undefined) "+d+" = false; if ("+d+" === undefined) "+d+" = "+b+" "+E,$||(n+="="),n+=" 0;"}n+=""+p+"if (!"+d+") { ";var i=t,B=B||[];B.push(n),n="",e.createErrors!==!1?(n+=" { keyword: '"+(i||"_formatLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+'" , params: { limit: ',n+=F?""+x:""+e.util.toQuotedString(s),n+=" } ",e.opts.messages!==!1&&(n+=" , message: 'should be "+k+' "',n+=F?"' + "+x+" + '":""+e.util.escapeQuotes(s),n+="\"' "),e.opts.verbose&&(n+=" , schema: ",n+=F?"validate.schema"+a:""+e.util.toQuotedString(s),n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ";var _=n;return n=B.pop(),n+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+_+"]); ":" validate.errors = ["+_+"]; return false; ":" var err = "+_+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+="}"}},function(e,t){"use strict";e.exports=function(e,t){var i,n=" ",r=e.level,o=e.dataLevel,s=e.schema[t],a=e.schemaPath+"."+t,l=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,h="data"+(o||""),d="valid"+r,u="key"+r,f="patternMatched"+r,p="";n+="var "+d+" = true;";var m=s;if(m)for(var g,v=-1,w=m.length-1;w>v;){g=m[v+=1],n+=" var "+f+" = false; for (var "+u+" in "+h+") { "+f+" = "+e.usePattern(g)+".test("+u+"); if ("+f+") break; } ";var y=e.util.escapeQuotes(g);n+=" if (!"+f+") { "+d+" = false; var err = ",e.createErrors!==!1?(n+=" { keyword: '"+(i||"patternRequired")+"' , dataPath: (dataPath || '') + "+e.errorPath+' , schemaPath: "'+l+"\" , params: { missingPattern: '"+y+"' } ",e.opts.messages!==!1&&(n+=" , message: 'should have property matching pattern \\'"+y+"\\'' "),e.opts.verbose&&(n+=" , schema: validate.schema"+a+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),n+=" } "):n+=" {} ",n+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } ",c&&(p+="}",n+=" else { ")}return n+=""+p}},function(e,t){e.exports={id:"https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#",$schema:"http://json-schema.org/draft-04/schema#",description:"Core schema meta-schema (v5 proposals)",definitions:{schemaArray:{type:"array",minItems:1,items:{$ref:"#"}},positiveInteger:{type:"integer",minimum:0},positiveIntegerDefault0:{allOf:[{$ref:"#/definitions/positiveInteger"},{"default":0}]},simpleTypes:{"enum":["array","boolean","integer","null","number","object","string"]},stringArray:{type:"array",items:{type:"string"},minItems:1,uniqueItems:!0},$data:{type:"object",required:["$data"],properties:{$data:{type:"string",format:"relative-json-pointer"}},additionalProperties:!1}},type:"object",properties:{id:{type:"string",format:"uri"},$schema:{type:"string",format:"uri"},title:{type:"string"},description:{type:"string"},"default":{},multipleOf:{anyOf:[{type:"number",minimum:0,exclusiveMinimum:!0},{$ref:"#/definitions/$data"}]},maximum:{anyOf:[{type:"number"},{$ref:"#/definitions/$data"}]},exclusiveMaximum:{anyOf:[{type:"boolean","default":!1},{$ref:"#/definitions/$data"}]},minimum:{anyOf:[{type:"number"},{$ref:"#/definitions/$data"}]},exclusiveMinimum:{anyOf:[{type:"boolean","default":!1},{$ref:"#/definitions/$data"}]},maxLength:{anyOf:[{$ref:"#/definitions/positiveInteger"},{$ref:"#/definitions/$data"}]},minLength:{anyOf:[{$ref:"#/definitions/positiveIntegerDefault0"},{$ref:"#/definitions/$data"}]},pattern:{anyOf:[{type:"string",format:"regex"},{$ref:"#/definitions/$data"}]},additionalItems:{anyOf:[{type:"boolean"},{$ref:"#"},{$ref:"#/definitions/$data"}],"default":{}},items:{anyOf:[{$ref:"#"},{$ref:"#/definitions/schemaArray"}],"default":{}},maxItems:{anyOf:[{$ref:"#/definitions/positiveInteger"},{$ref:"#/definitions/$data"}]},minItems:{anyOf:[{$ref:"#/definitions/positiveIntegerDefault0"},{$ref:"#/definitions/$data"}]},uniqueItems:{anyOf:[{type:"boolean","default":!1},{$ref:"#/definitions/$data"}]},maxProperties:{anyOf:[{$ref:"#/definitions/positiveInteger"},{$ref:"#/definitions/$data"}]},minProperties:{anyOf:[{$ref:"#/definitions/positiveIntegerDefault0"},{$ref:"#/definitions/$data"}]},required:{anyOf:[{$ref:"#/definitions/stringArray"},{$ref:"#/definitions/$data"}]},additionalProperties:{anyOf:[{type:"boolean"},{$ref:"#"},{$ref:"#/definitions/$data"}],"default":{}},definitions:{type:"object",additionalProperties:{$ref:"#"},"default":{}},properties:{type:"object",additionalProperties:{$ref:"#"},"default":{}},patternProperties:{type:"object",additionalProperties:{$ref:"#"},"default":{}},dependencies:{type:"object",additionalProperties:{anyOf:[{$ref:"#"},{$ref:"#/definitions/stringArray"}]}},"enum":{anyOf:[{type:"array",minItems:1,uniqueItems:!0},{$ref:"#/definitions/$data"}]},type:{anyOf:[{$ref:"#/definitions/simpleTypes"},{type:"array",items:{$ref:"#/definitions/simpleTypes"},minItems:1,uniqueItems:!0}]},allOf:{$ref:"#/definitions/schemaArray"},anyOf:{$ref:"#/definitions/schemaArray"},oneOf:{$ref:"#/definitions/schemaArray"},not:{$ref:"#"},format:{anyOf:[{type:"string"},{$ref:"#/definitions/$data"}]},formatMaximum:{anyOf:[{type:"string"},{$ref:"#/definitions/$data"}]},formatMinimum:{anyOf:[{type:"string"},{$ref:"#/definitions/$data"}]},exclusiveFormatMaximum:{anyOf:[{type:"boolean","default":!1},{$ref:"#/definitions/$data"}]},exclusiveFormatMinimum:{anyOf:[{type:"boolean","default":!1},{$ref:"#/definitions/$data"}]},constant:{anyOf:[{},{$ref:"#/definitions/$data"}]},contains:{$ref:"#"},patternGroups:{type:"object",additionalProperties:{type:"object",required:["schema"],properties:{maximum:{anyOf:[{$ref:"#/definitions/positiveInteger"},{$ref:"#/definitions/$data"}]},minimum:{anyOf:[{$ref:"#/definitions/positiveIntegerDefault0"},{$ref:"#/definitions/$data"}]},schema:{$ref:"#"}},additionalProperties:!1},"default":{}},"switch":{type:"array",items:{required:["then"],properties:{"if":{$ref:"#"},then:{anyOf:[{type:"boolean"},{$ref:"#"}]},"continue":{type:"boolean"}},additionalProperties:!1,dependencies:{"continue":["if"]}}}},dependencies:{exclusiveMaximum:["maximum"],exclusiveMinimum:["minimum"],formatMaximum:["format"],formatMinimum:["format"],exclusiveFormatMaximum:["formatMaximum"],exclusiveFormatMinimum:["formatMinimum"]},"default":{}}},function(e,t){"use strict";var i=/^[a-z_$][a-z0-9_$]*$/i;e.exports=function(e,t){function n(e,t,i){for(var n,r=0;ra;a++)r(s[a]);for(a=0;l>a;a++)n(e,s[a],t)}else s&&r(s),n(e,s,t)}this.RULES.keywords[e]=!0,this.RULES.all[e]=!0}},function(e,t){e.exports={id:"http://json-schema.org/draft-04/schema#",$schema:"http://json-schema.org/draft-04/schema#",description:"Core schema meta-schema",definitions:{schemaArray:{type:"array",minItems:1,items:{$ref:"#"}},positiveInteger:{type:"integer",minimum:0},positiveIntegerDefault0:{allOf:[{$ref:"#/definitions/positiveInteger"},{"default":0}]},simpleTypes:{"enum":["array","boolean","integer","null","number","object","string"]},stringArray:{type:"array",items:{type:"string"},minItems:1,uniqueItems:!0}},type:"object",properties:{id:{type:"string",format:"uri"},$schema:{type:"string",format:"uri"},title:{type:"string"},description:{type:"string"},"default":{},multipleOf:{type:"number",minimum:0,exclusiveMinimum:!0},maximum:{type:"number"},exclusiveMaximum:{type:"boolean","default":!1},minimum:{type:"number"},exclusiveMinimum:{type:"boolean","default":!1},maxLength:{$ref:"#/definitions/positiveInteger"},minLength:{$ref:"#/definitions/positiveIntegerDefault0"},pattern:{type:"string",format:"regex"},additionalItems:{anyOf:[{type:"boolean"},{$ref:"#"}],"default":{}},items:{anyOf:[{$ref:"#"},{$ref:"#/definitions/schemaArray"}],"default":{}},maxItems:{$ref:"#/definitions/positiveInteger"},minItems:{$ref:"#/definitions/positiveIntegerDefault0"},uniqueItems:{type:"boolean","default":!1},maxProperties:{$ref:"#/definitions/positiveInteger"},minProperties:{$ref:"#/definitions/positiveIntegerDefault0"},required:{$ref:"#/definitions/stringArray"},additionalProperties:{anyOf:[{type:"boolean"},{$ref:"#"}],"default":{}},definitions:{type:"object",additionalProperties:{$ref:"#"},"default":{}},properties:{type:"object",additionalProperties:{$ref:"#"},"default":{}},patternProperties:{type:"object",additionalProperties:{$ref:"#"},"default":{}},dependencies:{type:"object",additionalProperties:{anyOf:[{$ref:"#"},{$ref:"#/definitions/stringArray"}]}},"enum":{type:"array",minItems:1,uniqueItems:!0},type:{anyOf:[{$ref:"#/definitions/simpleTypes"},{type:"array",items:{$ref:"#/definitions/simpleTypes"},minItems:1,uniqueItems:!0}]},allOf:{$ref:"#/definitions/schemaArray"},anyOf:{$ref:"#/definitions/schemaArray"},oneOf:{$ref:"#/definitions/schemaArray"},not:{$ref:"#"}},dependencies:{exclusiveMaximum:["maximum"],exclusiveMinimum:["minimum"]},"default":{}}},function(e,t,i){"use strict";var n=i(52),r=i(53),o=i(56),s=i(57),a=i(58),l=i(61),c=i(54),h={};h.create=function(e,t){if(!e)throw new Error("No container element provided.");this.container=e,this.dom={},this.highlighter=new n,this.selection=void 0,this.multiselection={nodes:[]},this.validateSchema=null,this.errorNodes=[],this.node=null,this.focusTarget=null,this._setOptions(t),this.options.history&&"view"!==this.options.mode&&(this.history=new r(this)),this._createFrame(),this._createTable()},h.destroy=function(){this.frame&&this.container&&this.frame.parentNode==this.container&&(this.container.removeChild(this.frame),this.frame=null),this.container=null,this.dom=null,this.clear(),this.node=null,this.focusTarget=null,this.selection=null,this.multiselection=null,this.errorNodes=null,this.validateSchema=null,this._debouncedValidate=null,this.history&&(this.history.destroy(),this.history=null),this.searchBox&&(this.searchBox.destroy(),this.searchBox=null),this.modeSwitcher&&(this.modeSwitcher.destroy(),this.modeSwitcher=null)},h._setOptions=function(e){if(this.options={search:!0,history:!0,mode:"tree",name:void 0,schema:null},e)for(var t in e)e.hasOwnProperty(t)&&(this.options[t]=e[t]);this.setSchema(this.options.schema),this._debouncedValidate=c.debounce(this.validate.bind(this),this.DEBOUNCE_INTERVAL)},h.set=function(e,t){if(t&&(console.warn('Second parameter "name" is deprecated. Use setName(name) instead.'),this.options.name=t),e instanceof Function||void 0===e)this.clear();else{this.content.removeChild(this.table);var i={field:this.options.name,value:e},n=new a(this,i);this._setRoot(n),this.validate();var r=!1;this.node.expand(r),this.content.appendChild(this.table)}this.history&&this.history.clear(),this.searchBox&&this.searchBox.clear()},h.get=function(){if(this.focusTarget){var e=a.getNodeFromTarget(this.focusTarget);e&&e.blur()}return this.node?this.node.getValue():void 0},h.getText=function(){return JSON.stringify(this.get())},h.setText=function(e){this.set(c.parse(e))},h.setName=function(e){this.options.name=e,this.node&&this.node.updateField(this.options.name)},h.getName=function(){return this.options.name},h.focus=function(){var e=this.content.querySelector("[contenteditable=true]");e?e.focus():this.node.dom.expand?this.node.dom.expand.focus():this.node.dom.menu?this.node.dom.menu.focus():(e=this.frame.querySelector("button"),e&&e.focus())},h.clear=function(){this.node&&(this.node.collapse(),this.tbody.removeChild(this.node.getDom()),delete this.node)},h._setRoot=function(e){this.clear(),this.node=e,this.tbody.appendChild(e.getDom())},h.search=function(e){var t;return this.node?(this.content.removeChild(this.table),t=this.node.search(e),this.content.appendChild(this.table)):t=[],t},h.expandAll=function(){this.node&&(this.content.removeChild(this.table),this.node.expand(),this.content.appendChild(this.table))},h.collapseAll=function(){this.node&&(this.content.removeChild(this.table),this.node.collapse(),this.content.appendChild(this.table))},h._onAction=function(e,t){this.history&&this.history.add(e,t),this._onChange()},h._onChange=function(){if(this._debouncedValidate(),this.options.onChange)try{this.options.onChange()}catch(e){console.error("Error in onChange callback: ",e)}},h.validate=function(){this.errorNodes&&this.errorNodes.forEach(function(e){e.setError(null)});var e=this.node;if(e){var t=e.validate(),i=[];if(this.validateSchema){var n=this.validateSchema(e.getValue());n||(i=this.validateSchema.errors.map(function(e){return c.improveSchemaError(e)}).map(function(t){return{node:e.findNode(t.dataPath),error:t}}).filter(function(e){return null!=e.node}))}this.errorNodes=t.concat(i).reduce(function(e,t){return t.node.findParents().map(function(e){return{node:e,child:t.node,error:{message:"object"===e.type?"Contains invalid properties":"Contains invalid items"}}}).concat(e,[t])},[]).map(function(e){return e.node.setError(e.error,e.child),e.node})}},h.refresh=function(){this.node&&this.node.updateDom({recurse:!0})},h.startAutoScroll=function(e){var t=this,i=this.content,n=c.getAbsoluteTop(i),r=i.clientHeight,o=n+r,s=24,a=50;n+s>e&&i.scrollTop>0?this.autoScrollStep=(n+s-e)/3:e>o-s&&r+i.scrollTop3?(i.scrollTop+=r/3,n.animateCallback=t,n.animateTimeout=setTimeout(a,50)):(t&&t(!0),i.scrollTop=s,delete n.animateTimeout,delete n.animateCallback)};a()}else t&&t(!1)},h._createFrame=function(){function e(e){t._onEvent&&t._onEvent(e)}this.frame=document.createElement("div"),this.frame.className="jsoneditor jsoneditor-mode-"+this.options.mode,this.container.appendChild(this.frame);var t=this;this.frame.onclick=function(t){var i=t.target;e(t),"BUTTON"==i.nodeName&&t.preventDefault()},this.frame.oninput=e,this.frame.onchange=e,this.frame.onkeydown=e,this.frame.onkeyup=e,this.frame.oncut=e,this.frame.onpaste=e,this.frame.onmousedown=e,this.frame.onmouseup=e,this.frame.onmouseover=e,this.frame.onmouseout=e,c.addEventListener(this.frame,"focus",e,!0),c.addEventListener(this.frame,"blur",e,!0),this.frame.onfocusin=e,this.frame.onfocusout=e,this.menu=document.createElement("div"),this.menu.className="jsoneditor-menu",this.frame.appendChild(this.menu);var i=document.createElement("button");i.className="jsoneditor-expand-all",i.title="Expand all fields",i.onclick=function(){t.expandAll()},this.menu.appendChild(i);var n=document.createElement("button");if(n.title="Collapse all fields",n.className="jsoneditor-collapse-all",n.onclick=function(){t.collapseAll()},this.menu.appendChild(n),this.history){var r=document.createElement("button");r.className="jsoneditor-undo jsoneditor-separator",r.title="Undo last action (Ctrl+Z)",r.onclick=function(){t._onUndo()},this.menu.appendChild(r),this.dom.undo=r;var s=document.createElement("button");s.className="jsoneditor-redo",s.title="Redo (Ctrl+Shift+Z)",s.onclick=function(){t._onRedo()},this.menu.appendChild(s),this.dom.redo=s,this.history.onChange=function(){r.disabled=!t.history.canUndo(),s.disabled=!t.history.canRedo()},this.history.onChange()}if(this.options&&this.options.modes&&this.options.modes.length){var a=this;this.modeSwitcher=new l(this.menu,this.options.modes,this.options.mode,function(e){a.modeSwitcher.destroy(),a.setMode(e),a.modeSwitcher.focus()})}this.options.search&&(this.searchBox=new o(this,this.menu))},h._onUndo=function(){this.history&&(this.history.undo(),this._onChange())},h._onRedo=function(){this.history&&(this.history.redo(),this._onChange())},h._onEvent=function(e){"keydown"==e.type&&this._onKeyDown(e),"focus"==e.type&&(this.focusTarget=e.target),"mousedown"==e.type&&this._startDragDistance(e),"mousemove"!=e.type&&"mouseup"!=e.type&&"click"!=e.type||this._updateDragDistance(e);var t=a.getNodeFromTarget(e.target);if(t&&t.selected){if("click"==e.type){if(e.target==t.dom.menu)return void this.showContextMenu(e.target);e.hasMoved||this.deselect()}"mousedown"==e.type&&a.onDragStart(this.multiselection.nodes,e)}else"mousedown"==e.type&&(this.deselect(),t&&e.target==t.dom.drag?a.onDragStart(t,e):(!t||e.target!=t.dom.field&&e.target!=t.dom.value&&e.target!=t.dom.select)&&this._onMultiSelectStart(e));t&&t.onEvent(e)},h._startDragDistance=function(e){this.dragDistanceEvent={initialTarget:e.target,initialPageX:e.pageX,initialPageY:e.pageY,dragDistance:0,hasMoved:!1}},h._updateDragDistance=function(e){this.dragDistanceEvent||this._startDragDistance(e);var t=e.pageX-this.dragDistanceEvent.initialPageX,i=e.pageY-this.dragDistanceEvent.initialPageY;return this.dragDistanceEvent.dragDistance=Math.sqrt(t*t+i*i),this.dragDistanceEvent.hasMoved=this.dragDistanceEvent.hasMoved||this.dragDistanceEvent.dragDistance>10,e.dragDistance=this.dragDistanceEvent.dragDistance,e.hasMoved=this.dragDistanceEvent.hasMoved,e.dragDistance},h._onMultiSelectStart=function(e){var t=a.getNodeFromTarget(e.target);if("tree"===this.options.mode&&void 0===this.options.onEditable){this.multiselection={start:t||null,end:null,nodes:[]},this._startDragDistance(e);var i=this;this.mousemove||(this.mousemove=c.addEventListener(window,"mousemove",function(e){i._onMultiSelect(e)})),this.mouseup||(this.mouseup=c.addEventListener(window,"mouseup",function(e){i._onMultiSelectEnd(e)}))}},h._onMultiSelect=function(e){if(e.preventDefault(),this._updateDragDistance(e),e.hasMoved){var t=a.getNodeFromTarget(e.target);t&&(null==this.multiselection.start&&(this.multiselection.start=t),this.multiselection.end=t),this.deselect();var i=this.multiselection.start,n=this.multiselection.end||this.multiselection.start;i&&n&&(this.multiselection.nodes=this._findTopLevelNodes(i,n),this.select(this.multiselection.nodes))}},h._onMultiSelectEnd=function(e){this.multiselection.nodes[0]&&this.multiselection.nodes[0].dom.menu.focus(),this.multiselection.start=null,this.multiselection.end=null,this.mousemove&&(c.removeEventListener(window,"mousemove",this.mousemove),delete this.mousemove),this.mouseup&&(c.removeEventListener(window,"mouseup",this.mouseup),delete this.mouseup)},h.deselect=function(e){this.multiselection.nodes.forEach(function(e){e.setSelected(!1)}),this.multiselection.nodes=[],e&&(this.multiselection.start=null,this.multiselection.end=null)},h.select=function(e){if(!Array.isArray(e))return this.select([e]);if(e){this.deselect(),this.multiselection.nodes=e.slice(0);var t=e[0];e.forEach(function(e){e.setSelected(!0,e===t)})}},h._findTopLevelNodes=function(e,t){for(var i=e.getNodePath(),n=t.getNodePath(),r=0;r=0},n.prototype.canRedo=function(){return this.index=0;){var t=c[e];if(" "!==t&&"\n"!==t&&"\r"!==t&&" "!==t)return t;e--}return""}function o(){for(h+=2;hn;n++){var o=i[n];o.style&&o.removeAttribute("style");var s=o.attributes;if(s)for(var a=s.length-1;a>=0;a--){var l=s[a];l.specified===!0&&o.removeAttribute(l.name)}t.stripFormatting(o)}},t.setEndOfContentEditable=function(e){var t,i;document.createRange&&(t=document.createRange(),t.selectNodeContents(e),t.collapse(!1),i=window.getSelection(),i.removeAllRanges(),i.addRange(t))},t.selectContentEditable=function(e){if(e&&"DIV"==e.nodeName){var t,i;window.getSelection&&document.createRange&&(i=document.createRange(),i.selectNodeContents(e),t=window.getSelection(),t.removeAllRanges(),t.addRange(i))}},t.getSelection=function(){if(window.getSelection){var e=window.getSelection();if(e.getRangeAt&&e.rangeCount)return e.getRangeAt(0)}return null},t.setSelection=function(e){if(e&&window.getSelection){var t=window.getSelection();t.removeAllRanges(),t.addRange(e)}},t.getSelectionOffset=function(){var e=t.getSelection();return e&&"startOffset"in e&&"endOffset"in e&&e.startContainer&&e.startContainer==e.endContainer?{startOffset:e.startOffset,endOffset:e.endOffset,container:e.startContainer.parentNode}:null},t.setSelectionOffset=function(e){if(document.createRange&&window.getSelection){var i=window.getSelection();if(i){var n=document.createRange();e.container.firstChild||e.container.appendChild(document.createTextNode("")),n.setStart(e.container.firstChild,e.startOffset),n.setEnd(e.container.firstChild,e.endOffset),t.setSelection(n)}}},t.getInnerText=function(e,i){var n=void 0==i;if(n&&(i={text:"",flush:function(){var e=this.text;return this.text="",e},set:function(e){this.text=e}}),e.nodeValue)return i.flush()+e.nodeValue;if(e.hasChildNodes()){for(var r=e.childNodes,o="",s=0,a=r.length;a>s;s++){var l=r[s];if("DIV"==l.nodeName||"P"==l.nodeName){var c=r[s-1],h=c?c.nodeName:void 0;h&&"DIV"!=h&&"P"!=h&&"BR"!=h&&(o+="\n",i.flush()),o+=t.getInnerText(l,i),i.set("\n")}else"BR"==l.nodeName?(o+=i.flush(),i.set("\n")):o+=t.getInnerText(l,i)}return o}return"P"==e.nodeName&&-1!=t.getInternetExplorerVersion()?i.flush():""},t.getInternetExplorerVersion=function(){if(-1==o){var e=-1;if("Microsoft Internet Explorer"==navigator.appName){var t=navigator.userAgent,i=new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");null!=i.exec(t)&&(e=parseFloat(RegExp.$1))}o=e}return o},t.isFirefox=function(){return-1!=navigator.userAgent.indexOf("Firefox")};var o=-1;t.addEventListener=function(e,i,n,r){if(e.addEventListener)return void 0===r&&(r=!1),"mousewheel"===i&&t.isFirefox()&&(i="DOMMouseScroll"),e.addEventListener(i,n,r),n;if(e.attachEvent){var o=function(){return n.call(e,window.event)};return e.attachEvent("on"+i,o),o}},t.removeEventListener=function(e,i,n,r){e.removeEventListener?(void 0===r&&(r=!1),"mousewheel"===i&&t.isFirefox()&&(i="DOMMouseScroll"),e.removeEventListener(i,n,r)):e.detachEvent&&e.detachEvent("on"+i,n)},t.parsePath=function s(e){var t,i;if(0===e.length)return[];var n=e.match(/^\.(\w+)/);if(n)t=n[1],i=e.substr(t.length+1);else{if("["!==e[0])throw new SyntaxError("Failed to parse path");var r=e.indexOf("]");if(-1===r)throw new SyntaxError("Character ] expected in path");if(1===r)throw new SyntaxError("Index expected after [");var o=e.substring(1,r);t="*"===o?o:JSON.parse(o),i=e.substr(r+1)}return[t].concat(s(i))},t.improveSchemaError=function(e){if("enum"===e.keyword&&Array.isArray(e.schema)){var t=e.schema;if(t){if(t=t.map(function(e){return JSON.stringify(e)}),t.length>5){var i=["("+(t.length-5)+" more...)"];t=t.slice(0,5),t.push(i)}e.message="should be equal to one of: "+t.join(", ")}}return"additionalProperties"===e.keyword&&(e.message="should NOT have additional property: "+e.params.additionalProperty),e},t.insideRect=function(e,t,i){var n=void 0!==i?i:0;return t.left-n>=e.left&&t.right+n<=e.right&&t.top-n>=e.top&&t.bottom+n<=e.bottom},t.debounce=function(e,t,i){var n;return function(){var r=this,o=arguments,s=function(){n=null,i||e.apply(r,o)},a=i&&!n;clearTimeout(n),n=setTimeout(s,t),a&&e.apply(r,o)}},t.textDiff=function(e,t){for(var i=t.length,n=0,r=e.length,o=t.length;t.charAt(n)===e.charAt(n)&&i>n;)n++;for(;t.charAt(o-1)===e.charAt(r-1)&&o>n&&r>0;)o--,r--;return{start:n,end:o}}},function(e,t,i){var n=function(){var e={trace:function(){},yy:{},symbols_:{error:2,JSONString:3,STRING:4,JSONNumber:5,NUMBER:6,JSONNullLiteral:7,NULL:8,JSONBooleanLiteral:9,TRUE:10,FALSE:11,JSONText:12,JSONValue:13,EOF:14,JSONObject:15,JSONArray:16,"{":17,"}":18,JSONMemberList:19,JSONMember:20,":":21,",":22,"[":23,"]":24,JSONElementList:25,$accept:0,$end:1},terminals_:{2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},productions_:[0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],performAction:function(e,t,i,n,r,o,s){var a=o.length-1;switch(r){case 1:this.$=e.replace(/\\(\\|")/g,"$1").replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\v/g,"\x0B").replace(/\\f/g,"\f").replace(/\\b/g,"\b");break;case 2:this.$=Number(e);break;case 3:this.$=null;break;case 4:this.$=!0;break;case 5:this.$=!1;break;case 6:return this.$=o[a-1];case 13:this.$={};break;case 14:this.$=o[a-1];break;case 15:this.$=[o[a-2],o[a]];break;case 16:this.$={},this.$[o[a][0]]=o[a][1];break;case 17:this.$=o[a-2],o[a-2][o[a][0]]=o[a][1];break;case 18:this.$=[];break;case 19:this.$=o[a-1];break;case 20:this.$=[o[a]];break;case 21:this.$=o[a-2],o[a-2].push(o[a])}},table:[{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],defaultActions:{16:[2,6]},parseError:function(e,t){throw new Error(e)},parse:function(e){function t(e){r.length=r.length-2*e,o.length=o.length-e,s.length=s.length-e}function i(){var e;return e=n.lexer.lex()||1,"number"!=typeof e&&(e=n.symbols_[e]||e),e}var n=this,r=[0],o=[null],s=[],a=this.table,l="",c=0,h=0,d=0,u=2,f=1;this.lexer.setInput(e),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,"undefined"==typeof this.lexer.yylloc&&(this.lexer.yylloc={});var p=this.lexer.yylloc;s.push(p),"function"==typeof this.yy.parseError&&(this.parseError=this.yy.parseError);for(var m,g,v,w,y,A,C,E,b,F={};;){if(v=r[r.length-1],this.defaultActions[v]?w=this.defaultActions[v]:(null==m&&(m=i()),w=a[v]&&a[v][m]),"undefined"==typeof w||!w.length||!w[0]){if(!d){b=[];for(A in a[v])this.terminals_[A]&&A>2&&b.push("'"+this.terminals_[A]+"'");var x="";x=this.lexer.showPosition?"Parse error on line "+(c+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+b.join(", ")+", got '"+this.terminals_[m]+"'":"Parse error on line "+(c+1)+": Unexpected "+(1==m?"end of input":"'"+(this.terminals_[m]||m)+"'"),this.parseError(x,{text:this.lexer.match,token:this.terminals_[m]||m,line:this.lexer.yylineno,loc:p,expected:b})}if(3==d){if(m==f)throw new Error(x||"Parsing halted.");h=this.lexer.yyleng,l=this.lexer.yytext,c=this.lexer.yylineno,p=this.lexer.yylloc,m=i()}for(;;){if(u.toString()in a[v])break;if(0==v)throw new Error(x||"Parsing halted.");t(1),v=r[r.length-1]}g=m,m=u,v=r[r.length-1],w=a[v]&&a[v][u],d=3}if(w[0]instanceof Array&&w.length>1)throw new Error("Parse Error: multiple actions possible at state: "+v+", token: "+m);switch(w[0]){case 1:r.push(m),o.push(this.lexer.yytext),s.push(this.lexer.yylloc),r.push(w[1]),m=null,g?(m=g,g=null):(h=this.lexer.yyleng,l=this.lexer.yytext,c=this.lexer.yylineno,p=this.lexer.yylloc,d>0&&d--);break;case 2:if(C=this.productions_[w[1]][1],F.$=o[o.length-C],F._$={first_line:s[s.length-(C||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(C||1)].first_column,last_column:s[s.length-1].last_column},y=this.performAction.call(F,l,h,c,this.yy,w[1],o,s),"undefined"!=typeof y)return y;C&&(r=r.slice(0,-1*C*2),o=o.slice(0,-1*C),s=s.slice(0,-1*C)),r.push(this.productions_[w[1]][0]),o.push(F.$),s.push(F._$),E=a[r[r.length-2]][r[r.length-1]],r.push(E);break;case 3:return!0}}return!0}},t=function(){var e={EOF:1,parseError:function(e,t){if(!this.yy.parseError)throw new Error(e);this.yy.parseError(e,t)},setInput:function(e){return this._input=e,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this},input:function(){var e=this._input[0];this.yytext+=e,this.yyleng++,this.match+=e,this.matched+=e;var t=e.match(/\n/);return t&&this.yylineno++,this._input=this._input.slice(1),e},unput:function(e){return this._input=e+this._input,this},more:function(){return this._more=!0,this},less:function(e){this._input=this.match.slice(e)+this._input},pastInput:function(){var e=this.matched.substr(0,this.matched.length-this.match.length);return(e.length>20?"...":"")+e.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var e=this.match;return e.length<20&&(e+=this._input.substr(0,20-e.length)),(e.substr(0,20)+(e.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var e=this.pastInput(),t=new Array(e.length+1).join("-");return e+this.upcomingInput()+"\n"+t+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var e,t,i,n,r;this._more||(this.yytext="",this.match="");for(var o=this._currentRules(),s=0;st[0].length)||(t=i,n=s,this.options.flex));s++);return t?(r=t[0].match(/\n.*/g),r&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-1:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.yyleng=this.yytext.length,this._more=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],e=this.performAction.call(this,this.yy,this,o[n],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),e?e:void 0):""===this._input?this.EOF:void this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var e=this.next();return"undefined"!=typeof e?e:this.lex()},begin:function(e){this.conditionStack.push(e)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(e){this.begin(e)}};return e.options={},e.performAction=function(e,t,i,n){switch(i){case 0:break;case 1:return 6;case 2:return t.yytext=t.yytext.substr(1,t.yyleng-2),4;case 3:return 17;case 4:return 18;case 5:return 23;case 6:return 24;case 7:return 22;case 8:return 21;case 9:return 10;case 10:return 11;case 11:return 8;case 12:return 14;case 13:return"INVALID"}},e.rules=[/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt\/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/],e.conditions={INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13],inclusive:!0}},e}();return e.lexer=t,e}();t.parser=n,t.parse=n.parse.bind(n)},function(e,t){"use strict";function i(e,t){var i=this;this.editor=e,this.timeout=void 0,this.delay=200,this.lastText=void 0,this.dom={},this.dom.container=t;var n=document.createElement("table");this.dom.table=n,n.className="jsoneditor-search",t.appendChild(n);var r=document.createElement("tbody");this.dom.tbody=r,n.appendChild(r);var o=document.createElement("tr");r.appendChild(o);var s=document.createElement("td");o.appendChild(s);var a=document.createElement("div");this.dom.results=a,a.className="jsoneditor-results",s.appendChild(a),s=document.createElement("td"),o.appendChild(s);var l=document.createElement("div");this.dom.input=l,l.className="jsoneditor-frame",l.title="Search fields and values",s.appendChild(l);var c=document.createElement("table");l.appendChild(c);var h=document.createElement("tbody");c.appendChild(h),o=document.createElement("tr"),h.appendChild(o);var d=document.createElement("button");d.className="jsoneditor-refresh",s=document.createElement("td"),s.appendChild(d),o.appendChild(s);var u=document.createElement("input");this.dom.search=u,u.oninput=function(e){i._onDelayedSearch(e)},u.onchange=function(e){i._onSearch()},u.onkeydown=function(e){i._onKeyDown(e)},u.onkeyup=function(e){i._onKeyUp(e)},d.onclick=function(e){u.select()},s=document.createElement("td"),s.appendChild(u),o.appendChild(s);var f=document.createElement("button");f.title="Next result (Enter)",f.className="jsoneditor-next",f.onclick=function(){i.next()},s=document.createElement("td"),s.appendChild(f),o.appendChild(s);var p=document.createElement("button");p.title="Previous result (Shift+Enter)",p.className="jsoneditor-previous",p.onclick=function(){i.previous()},s=document.createElement("td"),s.appendChild(p),o.appendChild(s)}i.prototype.next=function(e){if(void 0!=this.results){var t=void 0!=this.resultIndex?this.resultIndex+1:0;t>this.results.length-1&&(t=0),this._setActiveResult(t,e)}},i.prototype.previous=function(e){if(void 0!=this.results){var t=this.results.length-1,i=void 0!=this.resultIndex?this.resultIndex-1:t;0>i&&(i=t),this._setActiveResult(i,e)}},i.prototype._setActiveResult=function(e,t){if(this.activeResult){var i=this.activeResult.node,n=this.activeResult.elem;"field"==n?delete i.searchFieldActive:delete i.searchValueActive,i.updateDom()}if(!this.results||!this.results[e])return this.resultIndex=void 0,void(this.activeResult=void 0);this.resultIndex=e;var r=this.results[this.resultIndex].node,o=this.results[this.resultIndex].elem;"field"==o?r.searchFieldActive=!0:r.searchValueActive=!0,this.activeResult=this.results[this.resultIndex],r.updateDom(),r.scrollTo(function(){t&&r.focus(o)})},i.prototype._clearDelay=function(){void 0!=this.timeout&&(clearTimeout(this.timeout),delete this.timeout)},i.prototype._onDelayedSearch=function(e){this._clearDelay();var t=this;this.timeout=setTimeout(function(e){t._onSearch()},this.delay)},i.prototype._onSearch=function(e){this._clearDelay();var t=this.dom.search.value,i=t.length>0?t:void 0;if(i!=this.lastText||e)if(this.lastText=i,this.results=this.editor.search(i),this._setActiveResult(void 0),void 0!=i){var n=this.results.length;switch(n){case 0:this.dom.results.innerHTML="no results";break;case 1:this.dom.results.innerHTML="1 result";break;default:this.dom.results.innerHTML=n+" results"}}else this.dom.results.innerHTML=""},i.prototype._onKeyDown=function(e){var t=e.which;27==t?(this.dom.search.value="",this._onSearch(),e.preventDefault(),e.stopPropagation()):13==t&&(e.ctrlKey?this._onSearch(!0):e.shiftKey?this.previous():this.next(),e.preventDefault(),e.stopPropagation())},i.prototype._onKeyUp=function(e){var t=e.keyCode;27!=t&&13!=t&&this._onDelayedSearch(e)},i.prototype.clear=function(){this.dom.search.value="",this._onSearch()},i.prototype.destroy=function(){this.editor=null,this.dom.container.removeChild(this.dom.table),this.dom=null,this.results=null,this.activeResult=null,this._clearDelay()},e.exports=i},function(e,t,i){"use strict";function n(e,t){function i(e,t,r){r.forEach(function(r){if("separator"==r.type){var o=document.createElement("div");o.className="jsoneditor-separator",a=document.createElement("li"),a.appendChild(o),e.appendChild(a)}else{var s={},a=document.createElement("li");e.appendChild(a);var l=document.createElement("button");if(l.className=r.className,s.button=l,r.title&&(l.title=r.title),r.click&&(l.onclick=function(e){e.preventDefault(),n.hide(),r.click()}),a.appendChild(l),r.submenu){var c=document.createElement("div");c.className="jsoneditor-icon",l.appendChild(c),l.appendChild(document.createTextNode(r.text));var h;if(r.click){l.className+=" jsoneditor-default";var d=document.createElement("button");s.buttonExpand=d,d.className="jsoneditor-expand",d.innerHTML='
',a.appendChild(d),r.submenuTitle&&(d.title=r.submenuTitle),h=d}else{var u=document.createElement("div");u.className="jsoneditor-expand",l.appendChild(u),h=l}h.onclick=function(e){e.preventDefault(),n._onExpandItem(s),h.focus()};var f=[];s.subItems=f;var p=document.createElement("ul");s.ul=p,p.className="jsoneditor-menu",p.style.height="0",a.appendChild(p),i(p,f,r.submenu)}else l.innerHTML='
'+r.text;t.push(s)}})}this.dom={};var n=this,r=this.dom;this.anchor=void 0,this.items=e,this.eventListeners={},this.selection=void 0,this.onClose=t?t.close:void 0;var o=document.createElement("div");o.className="jsoneditor-contextmenu-root",r.root=o;var s=document.createElement("div");s.className="jsoneditor-contextmenu",r.menu=s,o.appendChild(s);var a=document.createElement("ul");a.className="jsoneditor-menu",s.appendChild(a),r.list=a,r.items=[];var l=document.createElement("button");r.focusButton=l;var c=document.createElement("li");c.style.overflow="hidden",c.style.height="0",c.appendChild(l),a.appendChild(c),i(a,this.dom.items,e),this.maxHeight=0,e.forEach(function(t){var i=24*(e.length+(t.submenu?t.submenu.length:0));n.maxHeight=Math.max(n.maxHeight,i)})}var r=i(54);n.prototype._getVisibleButtons=function(){var e=[],t=this;return this.dom.items.forEach(function(i){e.push(i.button),i.buttonExpand&&e.push(i.buttonExpand),i.subItems&&i==t.expandedItem&&i.subItems.forEach(function(t){e.push(t.button),t.buttonExpand&&e.push(t.buttonExpand)})}),e},n.visibleMenu=void 0,n.prototype.show=function(e,t){this.hide();var i=!0;if(t){var o=e.getBoundingClientRect(),s=t.getBoundingClientRect();o.bottom+this.maxHeights.top&&(i=!1)}if(i){var a=e.offsetHeight;this.dom.menu.style.left="0px",this.dom.menu.style.top=a+"px",this.dom.menu.style.bottom=""}else this.dom.menu.style.left="0px",this.dom.menu.style.top="",this.dom.menu.style.bottom="0px";var l=e.parentNode;l.insertBefore(this.dom.root,l.firstChild);var c=this,h=this.dom.list;this.eventListeners.mousedown=r.addEventListener(window,"mousedown",function(e){var t=e.target;t==h||c._isChildOf(t,h)||(c.hide(),e.stopPropagation(),e.preventDefault())}),this.eventListeners.keydown=r.addEventListener(window,"keydown",function(e){c._onKeyDown(e)}),this.selection=r.getSelection(),this.anchor=e,setTimeout(function(){c.dom.focusButton.focus()},0),n.visibleMenu&&n.visibleMenu.hide(),n.visibleMenu=this},n.prototype.hide=function(){this.dom.root.parentNode&&(this.dom.root.parentNode.removeChild(this.dom.root),this.onClose&&this.onClose());for(var e in this.eventListeners)if(this.eventListeners.hasOwnProperty(e)){var t=this.eventListeners[e];t&&r.removeEventListener(window,e,t),delete this.eventListeners[e]}n.visibleMenu==this&&(n.visibleMenu=void 0)},n.prototype._onExpandItem=function(e){var t=this,i=e==this.expandedItem,n=this.expandedItem;if(n&&(n.ul.style.height="0",n.ul.style.padding="",setTimeout(function(){t.expandedItem!=n&&(n.ul.style.display="",r.removeClassName(n.ul.parentNode,"jsoneditor-selected"))},300),this.expandedItem=void 0),!i){var o=e.ul;o.style.display="block";o.clientHeight;setTimeout(function(){t.expandedItem==e&&(o.style.height=24*o.childNodes.length+"px",o.style.padding="5px 10px")},0),r.addClassName(o.parentNode,"jsoneditor-selected"),this.expandedItem=e}},n.prototype._onKeyDown=function(e){var t,i,n,o,s=e.target,a=e.which,l=!1;27==a?(this.selection&&r.setSelection(this.selection),this.anchor&&this.anchor.focus(),this.hide(),l=!0):9==a?e.shiftKey?(t=this._getVisibleButtons(),i=t.indexOf(s),0==i&&(t[t.length-1].focus(),l=!0)):(t=this._getVisibleButtons(),i=t.indexOf(s),i==t.length-1&&(t[0].focus(),l=!0)):37==a?("jsoneditor-expand"==s.className&&(t=this._getVisibleButtons(),i=t.indexOf(s),n=t[i-1],n&&n.focus()),l=!0):38==a?(t=this._getVisibleButtons(),i=t.indexOf(s),n=t[i-1],n&&"jsoneditor-expand"==n.className&&(n=t[i-2]),n||(n=t[t.length-1]),n&&n.focus(),l=!0):39==a?(t=this._getVisibleButtons(),i=t.indexOf(s),o=t[i+1],o&&"jsoneditor-expand"==o.className&&o.focus(),l=!0):40==a&&(t=this._getVisibleButtons(),i=t.indexOf(s),o=t[i+1],o&&"jsoneditor-expand"==o.className&&(o=t[i+2]),o||(o=t[0]),o&&(o.focus(),l=!0),l=!0),l&&(e.stopPropagation(),e.preventDefault())},n.prototype._isChildOf=function(e,t){for(var i=e.parentNode;i;){if(i==t)return!0;i=i.parentNode}return!1},e.exports=n},function(e,t,i){"use strict";function n(e,t){this.editor=e,this.dom={},this.expanded=!1,t&&t instanceof Object?(this.setField(t.field,t.fieldEditable),this.setValue(t.value,t.type)):(this.setField(""),this.setValue(null)),this._debouncedOnChangeValue=a.debounce(this._onChangeValue.bind(this),n.prototype.DEBOUNCE_INTERVAL),this._debouncedOnChangeField=a.debounce(this._onChangeField.bind(this),n.prototype.DEBOUNCE_INTERVAL)}var r=i(59),o=i(57),s=i(60),a=i(54);n.prototype.DEBOUNCE_INTERVAL=150,n.prototype._updateEditability=function(){if(this.editable={field:!0,value:!0},this.editor&&(this.editable.field="tree"===this.editor.options.mode,this.editable.value="view"!==this.editor.options.mode,("tree"===this.editor.options.mode||"form"===this.editor.options.mode)&&"function"==typeof this.editor.options.onEditable)){var e=this.editor.options.onEditable({field:this.field,value:this.value,path:this.getPath()});"boolean"==typeof e?(this.editable.field=e,this.editable.value=e):("boolean"==typeof e.field&&(this.editable.field=e.field),"boolean"==typeof e.value&&(this.editable.value=e.value))}},n.prototype.getPath=function(){for(var e=this,t=[];e;){var i=e.parent?"array"!=e.parent.type?e.field:e.index:void 0;void 0!==i&&t.unshift(i),e=e.parent}return t},n.prototype.findNode=function(e){for(var t=a.parsePath(e),i=this;i&&t.length>0;){var n=t.shift();if("number"==typeof n){if("array"!==i.type)throw new Error("Cannot get child node at index "+n+": node is no array");i=i.childs[n]}else{if("object"!==i.type)throw new Error("Cannot get child node "+n+": node is no object");i=i.childs.filter(function(e){return e.field===n})[0]}}return i},n.prototype.findParents=function(){for(var e=[],t=this.parent;t;)e.unshift(t),t=t.parent;return e},n.prototype.setError=function(e,t){this.getDom(),this.error=e;var i=this.dom.tdError;if(e){i||(i=document.createElement("td"),this.dom.tdError=i,this.dom.tdValue.parentNode.appendChild(i));var n=document.createElement("div");n.className="jsoneditor-popover jsoneditor-right",n.appendChild(document.createTextNode(e.message));var r=document.createElement("button");for(r.className="jsoneditor-schema-error",r.appendChild(n),r.onmouseover=r.onfocus=function(){for(var e=["right","above","below","left"],t=0;ts;s++)i=e[s],void 0===i||i instanceof Function||(r=new n(this.editor,{value:i}),this.appendChild(r));this.value=""}else if("object"==this.type){this.childs=[];for(var l in e)e.hasOwnProperty(l)&&(i=e[l],void 0===i||i instanceof Function||(r=new n(this.editor,{field:l,value:i}),this.appendChild(r)));this.value="",this.editor.options.sortObjectKeys===!0&&this.sort("asc")}else this.childs=void 0,this.value=e;this.previousValue=this.value},n.prototype.getValue=function(){if("array"==this.type){var e=[];return this.childs.forEach(function(t){e.push(t.getValue())}),e}if("object"==this.type){var t={};return this.childs.forEach(function(e){t[e.getField()]=e.getValue()}),t}return void 0===this.value&&this._getDomValue(),this.value},n.prototype.getLevel=function(){return this.parent?this.parent.getLevel()+1:0},n.prototype.getNodePath=function(){var e=this.parent?this.parent.getNodePath():[];return e.push(this),e},n.prototype.clone=function(){var e=new n(this.editor);if(e.type=this.type,e.field=this.field,e.fieldInnerText=this.fieldInnerText,e.fieldEditable=this.fieldEditable,e.value=this.value,e.valueInnerText=this.valueInnerText,e.expanded=this.expanded,this.childs){var t=[];this.childs.forEach(function(i){var n=i.clone();n.setParent(e),t.push(n)}),e.childs=t}else e.childs=void 0;return e},n.prototype.expand=function(e){this.childs&&(this.expanded=!0,this.dom.expand&&(this.dom.expand.className="jsoneditor-expanded"),this.showChilds(),e!==!1&&this.childs.forEach(function(t){t.expand(e)}))},n.prototype.collapse=function(e){this.childs&&(this.hideChilds(),e!==!1&&this.childs.forEach(function(t){t.collapse(e)}),this.dom.expand&&(this.dom.expand.className="jsoneditor-collapsed"),this.expanded=!1)},n.prototype.showChilds=function(){var e=this.childs;if(e&&this.expanded){var t=this.dom.tr,i=t?t.parentNode:void 0;if(i){var n=this.getAppend(),r=t.nextSibling;r?i.insertBefore(n,r):i.appendChild(n),this.childs.forEach(function(e){i.insertBefore(e.getDom(),n),e.showChilds()})}}},n.prototype.hide=function(){var e=this.dom.tr,t=e?e.parentNode:void 0;t&&t.removeChild(e),this.hideChilds()},n.prototype.hideChilds=function(){var e=this.childs;if(e&&this.expanded){var t=this.getAppend();t.parentNode&&t.parentNode.removeChild(t),this.childs.forEach(function(e){e.hide()})}},n.prototype.appendChild=function(e){if(this._hasChilds()){if(e.setParent(this),e.fieldEditable="object"==this.type,"array"==this.type&&(e.index=this.childs.length),this.childs.push(e),this.expanded){var t=e.getDom(),i=this.getAppend(),n=i?i.parentNode:void 0; +i&&n&&n.insertBefore(t,i),e.showChilds()}this.updateDom({updateIndexes:!0}),e.updateDom({recurse:!0})}},n.prototype.moveBefore=function(e,t){if(this._hasChilds()){var i=this.dom.tr?this.dom.tr.parentNode:void 0;if(i){var n=document.createElement("tr");n.style.height=i.clientHeight+"px",i.appendChild(n)}e.parent&&e.parent.removeChild(e),t instanceof l?this.appendChild(e):this.insertBefore(e,t),i&&i.removeChild(n)}},n.prototype.moveTo=function(e,t){if(e.parent==this){var i=this.childs.indexOf(e);t>i&&t++}var n=this.childs[t]||this.append;this.moveBefore(e,n)},n.prototype.insertBefore=function(e,t){if(this._hasChilds()){if(t==this.append)e.setParent(this),e.fieldEditable="object"==this.type,this.childs.push(e);else{var i=this.childs.indexOf(t);if(-1==i)throw new Error("Node not found");e.setParent(this),e.fieldEditable="object"==this.type,this.childs.splice(i,0,e)}if(this.expanded){var n=e.getDom(),r=t.getDom(),o=r?r.parentNode:void 0;r&&o&&o.insertBefore(n,r),e.showChilds()}this.updateDom({updateIndexes:!0}),e.updateDom({recurse:!0})}},n.prototype.insertAfter=function(e,t){if(this._hasChilds()){var i=this.childs.indexOf(t),n=this.childs[i+1];n?this.insertBefore(e,n):this.appendChild(e)}},n.prototype.search=function(e){var t,i=[],n=e?e.toLowerCase():void 0;if(delete this.searchField,delete this.searchValue,void 0!=this.field){var r=String(this.field).toLowerCase();t=r.indexOf(n),-1!=t&&(this.searchField=!0,i.push({node:this,elem:"field"})),this._updateDomField()}if(this._hasChilds()){if(this.childs){var o=[];this.childs.forEach(function(t){o=o.concat(t.search(e))}),i=i.concat(o)}if(void 0!=n){var s=!1;0==o.length?this.collapse(s):this.expand(s)}}else{if(void 0!=this.value){var a=String(this.value).toLowerCase();t=a.indexOf(n),-1!=t&&(this.searchValue=!0,i.push({node:this,elem:"value"}))}this._updateDomValue()}return i},n.prototype.scrollTo=function(e){if(!this.dom.tr||!this.dom.tr.parentNode)for(var t=this.parent,i=!1;t;)t.expand(i),t=t.parent;this.dom.tr&&this.dom.tr.parentNode&&this.editor.scrollTo(this.dom.tr.offsetTop,e)},n.focusElement=void 0,n.prototype.focus=function(e){if(n.focusElement=e,this.dom.tr&&this.dom.tr.parentNode){var t=this.dom;switch(e){case"drag":t.drag?t.drag.focus():t.menu.focus();break;case"menu":t.menu.focus();break;case"expand":this._hasChilds()?t.expand.focus():t.field&&this.fieldEditable?(t.field.focus(),a.selectContentEditable(t.field)):t.value&&!this._hasChilds()?(t.value.focus(),a.selectContentEditable(t.value)):t.menu.focus();break;case"field":t.field&&this.fieldEditable?(t.field.focus(),a.selectContentEditable(t.field)):t.value&&!this._hasChilds()?(t.value.focus(),a.selectContentEditable(t.value)):this._hasChilds()?t.expand.focus():t.menu.focus();break;case"value":default:t.value&&!this._hasChilds()?(t.value.focus(),a.selectContentEditable(t.value)):t.field&&this.fieldEditable?(t.field.focus(),a.selectContentEditable(t.field)):this._hasChilds()?t.expand.focus():t.menu.focus()}}},n.select=function(e){setTimeout(function(){a.selectContentEditable(e)},0)},n.prototype.blur=function(){this._getDomValue(!1),this._getDomField(!1)},n.prototype.containsNode=function(e){if(this==e)return!0;var t=this.childs;if(t)for(var i=0,n=t.length;n>i;i++)if(t[i].containsNode(e))return!0;return!1},n.prototype._move=function(e,t){if(e!=t){if(e.containsNode(this))throw new Error("Cannot move a field into a child of itself");e.parent&&e.parent.removeChild(e);var i=e.clone();e.clearDom(),t?this.insertBefore(i,t):this.appendChild(i)}},n.prototype.removeChild=function(e){if(this.childs){var t=this.childs.indexOf(e);if(-1!=t){e.hide(),delete e.searchField,delete e.searchValue;var i=this.childs.splice(t,1)[0];return i.parent=null,this.updateDom({updateIndexes:!0}),i}}},n.prototype._remove=function(e){this.removeChild(e)},n.prototype.changeType=function(e){var t=this.type;if(t!=e){if("string"!=e&&"auto"!=e||"string"!=t&&"auto"!=t){var i,n=this.dom.tr?this.dom.tr.parentNode:void 0;i=this.expanded?this.getAppend():this.getDom();var r=i&&i.parentNode?i.nextSibling:void 0;this.hide(),this.clearDom(),this.type=e,"object"==e?(this.childs||(this.childs=[]),this.childs.forEach(function(e,t){e.clearDom(),delete e.index,e.fieldEditable=!0,void 0==e.field&&(e.field="")}),"string"!=t&&"auto"!=t||(this.expanded=!0)):"array"==e?(this.childs||(this.childs=[]),this.childs.forEach(function(e,t){e.clearDom(),e.fieldEditable=!1,e.index=t}),"string"!=t&&"auto"!=t||(this.expanded=!0)):this.expanded=!1,n&&(r?n.insertBefore(this.getDom(),r):n.appendChild(this.getDom())),this.showChilds()}else this.type=e;"auto"!=e&&"string"!=e||("string"==e?this.value=String(this.value):this.value=this._stringCast(String(this.value)),this.focus()),this.updateDom({updateIndexes:!0})}},n.prototype._getDomValue=function(e){if(this.dom.value&&"array"!=this.type&&"object"!=this.type&&(this.valueInnerText=a.getInnerText(this.dom.value)),void 0!=this.valueInnerText)try{var t;if("string"==this.type)t=this._unescapeHTML(this.valueInnerText);else{var i=this._unescapeHTML(this.valueInnerText);t=this._stringCast(i)}t!==this.value&&(this.value=t,this._debouncedOnChangeValue())}catch(n){if(this.value=void 0,e!==!0)throw n}},n.prototype._onChangeValue=function(){var e=this.editor.getSelection();if(e.range){var t=a.textDiff(String(this.value),String(this.previousValue));e.range.startOffset=t.start,e.range.endOffset=t.end}var i=this.editor.getSelection();if(i.range){var n=a.textDiff(String(this.previousValue),String(this.value));i.range.startOffset=n.start,i.range.endOffset=n.end}this.editor._onAction("editValue",{node:this,oldValue:this.previousValue,newValue:this.value,oldSelection:e,newSelection:i}),this.previousValue=this.value},n.prototype._onChangeField=function(){var e=this.editor.getSelection();if(e.range){var t=a.textDiff(this.field,this.previousField);e.range.startOffset=t.start,e.range.endOffset=t.end}var i=this.editor.getSelection();if(i.range){var n=a.textDiff(this.previousField,this.field);i.range.startOffset=n.start,i.range.endOffset=n.end}this.editor._onAction("editField",{node:this,oldValue:this.previousField,newValue:this.field,oldSelection:e,newSelection:i}),this.previousField=this.field},n.prototype._updateDomValue=function(){var e=this.dom.value;if(e){var t=["jsoneditor-value"],i=this.value,n="auto"==this.type?a.type(i):this.type,r="string"==n&&a.isUrl(i);t.push("jsoneditor-"+n),r&&t.push("jsoneditor-url");var o=""==String(this.value)&&"array"!=this.type&&"object"!=this.type;if(o&&t.push("jsoneditor-empty"),this.searchValueActive&&t.push("jsoneditor-highlight-active"),this.searchValue&&t.push("jsoneditor-highlight"),e.className=t.join(" "),"array"==n||"object"==n){var s=this.childs?this.childs.length:0;e.title=this.type+" containing "+s+" items"}else r&&this.editable.value?e.title="Ctrl+Click or Ctrl+Enter to open url in new window":e.title="";if("boolean"===n&&this.editable.value?(this.dom.checkbox||(this.dom.checkbox=document.createElement("input"),this.dom.checkbox.type="checkbox",this.dom.tdCheckbox=document.createElement("td"),this.dom.tdCheckbox.className="jsoneditor-tree",this.dom.tdCheckbox.appendChild(this.dom.checkbox),this.dom.tdValue.parentNode.insertBefore(this.dom.tdCheckbox,this.dom.tdValue)),this.dom.checkbox.checked=this.value):this.dom.tdCheckbox&&(this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox),delete this.dom.tdCheckbox,delete this.dom.checkbox),this["enum"]&&this.editable.value){if(!this.dom.select){this.dom.select=document.createElement("select"),this.id=this.field+"_"+(new Date).getUTCMilliseconds(),this.dom.select.id=this.id,this.dom.select.name=this.dom.select.id,this.dom.select.option=document.createElement("option"),this.dom.select.option.value="",this.dom.select.option.innerHTML="--",this.dom.select.appendChild(this.dom.select.option);for(var l=0;l0&&(e=this.childs.filter(function(e){return-1!==i.indexOf(e.field)}).map(function(e){return{node:e,error:{message:'duplicate key "'+e.field+'"'}}}))}if(this.childs)for(var n=0;n0&&(e=e.concat(o))}return e},n.prototype.clearDom=function(){this.dom={}},n.prototype.getDom=function(){var e=this.dom;if(e.tr)return e.tr;if(this._updateEditability(),e.tr=document.createElement("tr"),e.tr.node=this,"tree"===this.editor.options.mode){var t=document.createElement("td");if(this.editable.field&&this.parent){var i=document.createElement("button");e.drag=i,i.className="jsoneditor-dragarea",i.title="Drag to move this field (Alt+Shift+Arrows)",t.appendChild(i)}e.tr.appendChild(t);var n=document.createElement("td"),r=document.createElement("button");e.menu=r,r.className="jsoneditor-contextmenu",r.title="Click to open the actions menu (Ctrl+M)",n.appendChild(e.menu),e.tr.appendChild(n)}var o=document.createElement("td");return e.tr.appendChild(o),e.tree=this._createDomTree(),o.appendChild(e.tree),this.updateDom({updateIndexes:!0}),e.tr},n.onDragStart=function(e,t){if(!Array.isArray(e))return n.onDragStart([e],t);if(0!==e.length){var i=e[0],r=e[e.length-1],o=n.getNodeFromTarget(t.target),s=r._nextSibling(),l=i.editor,c=a.getAbsoluteTop(o.dom.tr)-a.getAbsoluteTop(i.dom.tr);l.mousemove||(l.mousemove=a.addEventListener(window,"mousemove",function(t){n.onDrag(e,t)})),l.mouseup||(l.mouseup=a.addEventListener(window,"mouseup",function(t){n.onDragEnd(e,t)})),l.highlighter.lock(),l.drag={oldCursor:document.body.style.cursor,oldSelection:l.getSelection(),oldBeforeNode:s,mouseX:t.pageX,offsetY:c,level:i.getLevel()},document.body.style.cursor="move",t.preventDefault()}},n.onDrag=function(e,t){if(!Array.isArray(e))return n.onDrag([e],t);if(0!==e.length){var i,r,o,s,c,h,d,u,f,p,m,g,v,w,y=e[0].editor,A=t.pageY-y.drag.offsetY,C=t.pageX,E=!1,b=e[0];if(i=b.dom.tr,f=a.getAbsoluteTop(i),g=i.offsetHeight,f>A){r=i;do r=r.previousSibling,d=n.getNodeFromTarget(r),p=r?a.getAbsoluteTop(r):0;while(r&&p>A);d&&!d.parent&&(d=void 0),d||(h=i.parentNode.firstChild,r=h?h.nextSibling:void 0,d=n.getNodeFromTarget(r),d==b&&(d=void 0)),d&&(r=d.dom.tr,p=r?a.getAbsoluteTop(r):0,A>p+g&&(d=void 0)),d&&(e.forEach(function(e){d.parent.moveBefore(e,d)}),E=!0)}else{var F=e[e.length-1];if(c=F.expanded&&F.append?F.append.getDom():F.dom.tr,s=c?c.nextSibling:void 0){m=a.getAbsoluteTop(s),o=s;do u=n.getNodeFromTarget(o),o&&(v=o.nextSibling?a.getAbsoluteTop(o.nextSibling):0,w=o?v-m:0,u.parent.childs.length==e.length&&u.parent.childs[e.length-1]==F&&(f+=27)),o=o.nextSibling;while(o&&A>f+w);if(u&&u.parent){var x=C-y.drag.mouseX,S=Math.round(x/24/2),$=y.drag.level+S,D=u.getLevel();for(r=u.dom.tr.previousSibling;$>D&&r;){d=n.getNodeFromTarget(r);var k=e.some(function(e){return e===d||d._isChildOf(e)});if(k);else{if(!(d instanceof l))break;var B=d.parent.childs;if(B.length==e.length&&B[e.length-1]==F)break;u=n.getNodeFromTarget(r),D=u.getLevel()}r=r.previousSibling}c.nextSibling!=u.dom.tr&&(e.forEach(function(e){u.parent.moveBefore(e,u)}),E=!0)}}}E&&(y.drag.mouseX=C,y.drag.level=b.getLevel()),y.startAutoScroll(A),t.preventDefault()}},n.onDragEnd=function(e,t){if(!Array.isArray(e))return n.onDrag([e],t);if(0!==e.length){var i=e[0],r=i.editor,o=i.parent,s=o.childs.indexOf(i),l=o.childs[s+e.length]||o.append;e[0]&&e[0].dom.menu.focus();var c={nodes:e,oldSelection:r.drag.oldSelection,newSelection:r.getSelection(),oldBeforeNode:r.drag.oldBeforeNode,newBeforeNode:l};c.oldBeforeNode!=c.newBeforeNode&&r._onAction("moveNodes",c),document.body.style.cursor=r.drag.oldCursor,r.highlighter.unlock(),e.forEach(function(e){t.target!==e.dom.drag&&t.target!==e.dom.menu&&r.highlighter.unhighlight()}),delete r.drag,r.mousemove&&(a.removeEventListener(window,"mousemove",r.mousemove),delete r.mousemove),r.mouseup&&(a.removeEventListener(window,"mouseup",r.mouseup),delete r.mouseup),r.stopAutoScroll(),t.preventDefault()}},n.prototype._isChildOf=function(e){for(var t=this.parent;t;){if(t==e)return!0;t=t.parent}return!1},n.prototype._createDomField=function(){return document.createElement("div")},n.prototype.setHighlight=function(e){this.dom.tr&&(e?a.addClassName(this.dom.tr,"jsoneditor-highlight"):a.removeClassName(this.dom.tr,"jsoneditor-highlight"),this.append&&this.append.setHighlight(e),this.childs&&this.childs.forEach(function(t){t.setHighlight(e)}))},n.prototype.setSelected=function(e,t){this.selected=e,this.dom.tr&&(e?a.addClassName(this.dom.tr,"jsoneditor-selected"):a.removeClassName(this.dom.tr,"jsoneditor-selected"),t?a.addClassName(this.dom.tr,"jsoneditor-first"):a.removeClassName(this.dom.tr,"jsoneditor-first"),this.append&&this.append.setSelected(e),this.childs&&this.childs.forEach(function(t){t.setSelected(e)}))},n.prototype.updateValue=function(e){this.value=e,this.updateDom()},n.prototype.updateField=function(e){this.field=e,this.updateDom()},n.prototype.updateDom=function(e){var t=this.dom.tree;t&&(t.style.marginLeft=24*this.getLevel()+"px");var i=this.dom.field;if(i){this.fieldEditable?(i.contentEditable=this.editable.field,i.spellcheck=!1,i.className="jsoneditor-field"):i.className="jsoneditor-readonly";var n;n=void 0!=this.index?this.index:void 0!=this.field?this.field:this._hasChilds()?this.type:"",i.innerHTML=this._escapeHTML(n),this._updateSchema()}var r=this.dom.value;if(r){var o=this.childs?this.childs.length:0;"array"==this.type?(r.innerHTML="["+o+"]",a.addClassName(this.dom.tr,"jsoneditor-expandable")):"object"==this.type?(r.innerHTML="{"+o+"}",a.addClassName(this.dom.tr,"jsoneditor-expandable")):(r.innerHTML=this._escapeHTML(this.value),a.removeClassName(this.dom.tr,"jsoneditor-expandable"))}this._updateDomField(),this._updateDomValue(),e&&e.updateIndexes===!0&&this._updateDomIndexes(),e&&e.recurse===!0&&this.childs&&this.childs.forEach(function(t){t.updateDom(e)}),this.append&&this.append.updateDom()},n.prototype._updateSchema=function(){this.editor&&this.editor.options&&(this.schema=n._findSchema(this.editor.options.schema,this.getPath()),this.schema?this["enum"]=n._findEnum(this.schema):delete this["enum"])},n._findEnum=function(e){if(e["enum"])return e["enum"];var t=e.oneOf||e.anyOf||e.allOf;if(t){var i=t.filter(function(e){return e["enum"]});if(i.length>0)return i[0]["enum"]}return null},n._findSchema=function(e,t){for(var i=e,n=0;n0?this.editor.multiselection.nodes:[this],A=y[0],C=y[y.length-1];if(13==u){if(f==this.dom.value)this.editable.value&&!e.ctrlKey||a.isUrl(this.value)&&(window.open(this.value,"_blank"),v=!0);else if(f==this.dom.expand){var E=this._hasChilds();if(E){var b=e.ctrlKey;this._onExpand(b),f.focus(),v=!0}}}else if(68==u)p&&w&&(n.onDuplicate(y),v=!0);else if(69==u)p&&(this._onExpand(m),f.focus(),v=!0);else if(77==u&&w)p&&(this.showContextMenu(f),v=!0);else if(46==u&&w)p&&(n.onRemove(y),v=!0);else if(45==u&&w)p&&!m?(this._onInsertBefore(),v=!0):p&&m&&(this._onInsertAfter(),v=!0);else if(35==u){if(g){var F=this._lastNode();F&&F.focus(n.focusElement||this._getElementName(f)),v=!0}}else if(36==u){if(g){var x=this._firstNode();x&&x.focus(n.focusElement||this._getElementName(f)),v=!0}}else if(37==u){if(g&&!m){var S=this._previousElement(f);S&&this.focus(this._getElementName(S)),v=!0}else if(g&&m&&w){if(C.expanded){var $=C.getAppend();r=$?$.nextSibling:void 0}else{var D=C.getDom();r=D.nextSibling}r&&(i=n.getNodeFromTarget(r),o=r.nextSibling,_=n.getNodeFromTarget(o),i&&i instanceof l&&1!=C.parent.childs.length&&_&&_.parent&&(s=this.editor.getSelection(),c=C._nextSibling(),y.forEach(function(e){_.parent.moveBefore(e,_)}),this.focus(n.focusElement||this._getElementName(f)),this.editor._onAction("moveNodes",{nodes:y,oldBeforeNode:c,newBeforeNode:_,oldSelection:s,newSelection:this.editor.getSelection()})))}}else if(38==u)g&&!m?(t=this._previousNode(),t&&(this.editor.deselect(!0),t.focus(n.focusElement||this._getElementName(f))),v=!0):!g&&p&&m&&w?(t=this._previousNode(),t&&(d=this.editor.multiselection,d.start=d.start||this,d.end=t,h=this.editor._findTopLevelNodes(d.start,d.end),this.editor.select(h),t.focus("field")),v=!0):g&&m&&w&&(t=A._previousNode(),t&&t.parent&&(s=this.editor.getSelection(),c=C._nextSibling(),y.forEach(function(e){t.parent.moveBefore(e,t)}),this.focus(n.focusElement||this._getElementName(f)),this.editor._onAction("moveNodes",{nodes:y,oldBeforeNode:c,newBeforeNode:t,oldSelection:s,newSelection:this.editor.getSelection()})),v=!0);else if(39==u){if(g&&!m){var k=this._nextElement(f);k&&this.focus(this._getElementName(k)),v=!0}else if(g&&m&&w){D=A.getDom();var B=D.previousSibling;B&&(t=n.getNodeFromTarget(B),t&&t.parent&&t instanceof l&&!t.isVisible()&&(s=this.editor.getSelection(),c=C._nextSibling(),y.forEach(function(e){t.parent.moveBefore(e,t)}),this.focus(n.focusElement||this._getElementName(f)),this.editor._onAction("moveNodes",{nodes:y,oldBeforeNode:c,newBeforeNode:t,oldSelection:s,newSelection:this.editor.getSelection()})))}}else if(40==u)if(g&&!m)i=this._nextNode(),i&&(this.editor.deselect(!0),i.focus(n.focusElement||this._getElementName(f))),v=!0;else if(!g&&p&&m&&w)i=this._nextNode(),i&&(d=this.editor.multiselection,d.start=d.start||this,d.end=i,h=this.editor._findTopLevelNodes(d.start,d.end),this.editor.select(h),i.focus("field")),v=!0;else if(g&&m&&w){i=C.expanded?C.append?C.append._nextNode():void 0:C._nextNode();var _=i&&(i._nextNode()||i.parent.append);_&&_.parent&&(s=this.editor.getSelection(),c=C._nextSibling(),y.forEach(function(e){_.parent.moveBefore(e,_)}),this.focus(n.focusElement||this._getElementName(f)),this.editor._onAction("moveNodes",{nodes:y,oldBeforeNode:c,newBeforeNode:_,oldSelection:s,newSelection:this.editor.getSelection()})),v=!0}v&&(e.preventDefault(),e.stopPropagation())},n.prototype._onExpand=function(e){if(e){var t=this.dom.tr.parentNode,i=t.parentNode,n=i.scrollTop;i.removeChild(t)}this.expanded?this.collapse(e):this.expand(e),e&&(i.appendChild(t),i.scrollTop=n)},n.onRemove=function(e){if(!Array.isArray(e))return n.onRemove([e]);if(e&&e.length>0){var t=e[0],i=t.parent,r=t.editor,o=t.getIndex();r.highlighter.unhighlight();var s=r.getSelection();n.blurNodes(e);var a=r.getSelection();e.forEach(function(e){e.parent._remove(e)}),r._onAction("removeNodes",{nodes:e.slice(0),parent:i,index:o,oldSelection:s,newSelection:a})}},n.onDuplicate=function(e){if(!Array.isArray(e))return n.onDuplicate([e]);if(e&&e.length>0){var t=e[e.length-1],i=t.parent,r=t.editor;r.deselect(r.multiselection.nodes);var o=r.getSelection(),s=t,a=e.map(function(e){var t=e.clone();return i.insertAfter(t,s),s=t,t});1===e.length?a[0].focus():r.select(a);var l=r.getSelection();r._onAction("duplicateNodes",{afterNode:t,nodes:a,parent:i,oldSelection:o,newSelection:l})}},n.prototype._onInsertBefore=function(e,t,i){var r=this.editor.getSelection(),o=new n(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:i});o.expand(!0),this.parent.insertBefore(o,this),this.editor.highlighter.unhighlight(),o.focus("field");var s=this.editor.getSelection();this.editor._onAction("insertBeforeNodes",{nodes:[o],beforeNode:this,parent:this.parent,oldSelection:r,newSelection:s})},n.prototype._onInsertAfter=function(e,t,i){var r=this.editor.getSelection(),o=new n(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:i});o.expand(!0),this.parent.insertAfter(o,this),this.editor.highlighter.unhighlight(),o.focus("field");var s=this.editor.getSelection();this.editor._onAction("insertAfterNodes",{nodes:[o],afterNode:this,parent:this.parent,oldSelection:r,newSelection:s})},n.prototype._onAppend=function(e,t,i){var r=this.editor.getSelection(),o=new n(this.editor,{field:void 0!=e?e:"",value:void 0!=t?t:"",type:i});o.expand(!0),this.parent.appendChild(o),this.editor.highlighter.unhighlight(),o.focus("field");var s=this.editor.getSelection();this.editor._onAction("appendNodes",{nodes:[o],parent:this.parent,oldSelection:r,newSelection:s})},n.prototype._onChangeType=function(e){var t=this.type;if(e!=t){var i=this.editor.getSelection();this.changeType(e);var n=this.editor.getSelection();this.editor._onAction("changeType",{node:this,oldType:t,newType:e,oldSelection:i,newSelection:n})}},n.prototype.sort=function(e){if(this._hasChilds()){var t="desc"==e?-1:1,i="array"==this.type?"value":"field";this.hideChilds();var n=this.childs,o=this.sortOrder;this.childs=this.childs.concat(),this.childs.sort(function(e,n){return t*r(e[i],n[i])}),this.sortOrder=1==t?"asc":"desc",this.editor._onAction("sort",{node:this,oldChilds:n,oldSort:o,newChilds:this.childs,newSort:this.sortOrder}),this.showChilds()}},n.prototype.getAppend=function(){return this.append||(this.append=new l(this.editor),this.append.setParent(this)),this.append.getDom()},n.getNodeFromTarget=function(e){for(;e;){if(e.node)return e.node;e=e.parentNode}},n.blurNodes=function(e){if(!Array.isArray(e))return void n.blurNodes([e]);var t=e[0],i=t.parent,r=t.getIndex();i.childs[r+e.length]?i.childs[r+e.length].focus():i.childs[r-1]?i.childs[r-1].focus():i.focus()},n.prototype._nextSibling=function(){var e=this.parent.childs.indexOf(this);return this.parent.childs[e+1]||this.parent.append},n.prototype._previousNode=function(){var e=null,t=this.getDom();if(t&&t.parentNode){var i=t;do i=i.previousSibling,e=n.getNodeFromTarget(i);while(i&&e instanceof l&&!e.isVisible())}return e},n.prototype._nextNode=function(){var e=null,t=this.getDom();if(t&&t.parentNode){var i=t;do i=i.nextSibling,e=n.getNodeFromTarget(i);while(i&&e instanceof l&&!e.isVisible())}return e},n.prototype._firstNode=function(){var e=null,t=this.getDom();if(t&&t.parentNode){var i=t.parentNode.firstChild;e=n.getNodeFromTarget(i)}return e},n.prototype._lastNode=function(){var e=null,t=this.getDom();if(t&&t.parentNode){var i=t.parentNode.lastChild;for(e=n.getNodeFromTarget(i);i&&e instanceof l&&!e.isVisible();)i=i.previousSibling,e=n.getNodeFromTarget(i)}return e},n.prototype._previousElement=function(e){var t=this.dom;switch(e){case t.value:if(this.fieldEditable)return t.field;case t.field:if(this._hasChilds())return t.expand;case t.expand:return t.menu;case t.menu:if(t.drag)return t.drag;default:return null}},n.prototype._nextElement=function(e){var t=this.dom;switch(e){case t.drag:return t.menu;case t.menu:if(this._hasChilds())return t.expand;case t.expand:if(this.fieldEditable)return t.field;case t.field:if(!this._hasChilds())return t.value;default:return null}},n.prototype._getElementName=function(e){var t=this.dom;for(var i in t)if(t.hasOwnProperty(i)&&t[i]==e)return i;return null},n.prototype._hasChilds=function(){return"array"==this.type||"object"==this.type},n.TYPE_TITLES={auto:'Field type "auto". The field type is automatically determined from the value and can be a string, number, boolean, or null.',object:'Field type "object". An object contains an unordered set of key/value pairs.',array:'Field type "array". An array contains an ordered collection of values.',string:'Field type "string". Field type is not determined from the value, but always returned as string.'},n.prototype.showContextMenu=function(e,t){var i=this,r=n.TYPE_TITLES,s=[];if(this.editable.value&&s.push({text:"Type",title:"Change the type of this field",className:"jsoneditor-type-"+this.type,submenu:[{text:"Auto",className:"jsoneditor-type-auto"+("auto"==this.type?" jsoneditor-selected":""),title:r.auto,click:function(){i._onChangeType("auto")}},{text:"Array",className:"jsoneditor-type-array"+("array"==this.type?" jsoneditor-selected":""),title:r.array,click:function(){i._onChangeType("array")}},{text:"Object",className:"jsoneditor-type-object"+("object"==this.type?" jsoneditor-selected":""),title:r.object,click:function(){i._onChangeType("object")}},{text:"String",className:"jsoneditor-type-string"+("string"==this.type?" jsoneditor-selected":""),title:r.string,click:function(){i._onChangeType("string")}}]}),this._hasChilds()){var a="asc"==this.sortOrder?"desc":"asc";s.push({text:"Sort",title:"Sort the childs of this "+this.type,className:"jsoneditor-sort-"+a,click:function(){i.sort(a)},submenu:[{text:"Ascending",className:"jsoneditor-sort-asc",title:"Sort the childs of this "+this.type+" in ascending order",click:function(){i.sort("asc")}},{text:"Descending",className:"jsoneditor-sort-desc",title:"Sort the childs of this "+this.type+" in descending order",click:function(){i.sort("desc")}}]})}if(this.parent&&this.parent._hasChilds()){s.length&&s.push({type:"separator"});var l=i.parent.childs;i==l[l.length-1]&&s.push({text:"Append",title:"Append a new field with type 'auto' after this field (Ctrl+Shift+Ins)",submenuTitle:"Select the type of the field to be appended",className:"jsoneditor-append",click:function(){i._onAppend("","","auto")},submenu:[{text:"Auto",className:"jsoneditor-type-auto",title:r.auto,click:function(){i._onAppend("","","auto")}},{text:"Array",className:"jsoneditor-type-array",title:r.array,click:function(){i._onAppend("",[])}},{text:"Object",className:"jsoneditor-type-object",title:r.object,click:function(){i._onAppend("",{})}},{text:"String",className:"jsoneditor-type-string",title:r.string,click:function(){i._onAppend("","","string")}}]}),s.push({text:"Insert",title:"Insert a new field with type 'auto' before this field (Ctrl+Ins)",submenuTitle:"Select the type of the field to be inserted",className:"jsoneditor-insert",click:function(){i._onInsertBefore("","","auto")},submenu:[{text:"Auto",className:"jsoneditor-type-auto",title:r.auto,click:function(){i._onInsertBefore("","","auto")}},{text:"Array",className:"jsoneditor-type-array", +title:r.array,click:function(){i._onInsertBefore("",[])}},{text:"Object",className:"jsoneditor-type-object",title:r.object,click:function(){i._onInsertBefore("",{})}},{text:"String",className:"jsoneditor-type-string",title:r.string,click:function(){i._onInsertBefore("","","string")}}]}),this.editable.field&&(s.push({text:"Duplicate",title:"Duplicate this field (Ctrl+D)",className:"jsoneditor-duplicate",click:function(){n.onDuplicate(i)}}),s.push({text:"Remove",title:"Remove this field (Ctrl+Del)",className:"jsoneditor-remove",click:function(){n.onRemove(i)}}))}var c=new o(s,{close:t});c.show(e,this.editor.content)},n.prototype._getType=function(e){return e instanceof Array?"array":e instanceof Object?"object":"string"==typeof e&&"string"!=typeof this._stringCast(e)?"string":"auto"},n.prototype._stringCast=function(e){var t=e.toLowerCase(),i=Number(e),n=parseFloat(e);return""==e?"":"null"==t?null:"true"==t?!0:"false"==t?!1:isNaN(i)||isNaN(n)?e:i},n.prototype._escapeHTML=function(e){if("string"!=typeof e)return String(e);var t=String(e).replace(/&/g,"&").replace(//g,">").replace(/ /g,"  ").replace(/^ /," ").replace(/ $/," "),i=JSON.stringify(t),n=i.substring(1,i.length-1);return this.editor.options.escapeUnicode===!0&&(n=a.escapeUnicodeChars(n)),n},n.prototype._unescapeHTML=function(e){var t='"'+this._escapeJSON(e)+'"',i=a.parse(t);return i.replace(/</g,"<").replace(/>/g,">").replace(/ |\u00A0/g," ").replace(/&/g,"&")},n.prototype._escapeJSON=function(e){for(var t="",i=0;im)return-1;if(m>g)return 1}for(var v=0,w=Math.max(f.length,p.length);w>v;v++){if(n=!(f[v]||"").match(c)&&parseFloat(f[v])||f[v]||0,r=!(p[v]||"").match(c)&&parseFloat(p[v])||p[v]||0,isNaN(n)!==isNaN(r))return isNaN(n)?1:-1;if(typeof n!=typeof r&&(n+="",r+=""),r>n)return-1;if(n>r)return 1}return 0}},function(e,t,i){"use strict";function n(e){function t(e){this.editor=e,this.dom={}}return t.prototype=new e,t.prototype.getDom=function(){var e=this.dom;if(e.tr)return e.tr;this._updateEditability();var t=document.createElement("tr");if(t.node=this,e.tr=t,"tree"===this.editor.options.mode){e.tdDrag=document.createElement("td");var i=document.createElement("td");e.tdMenu=i;var n=document.createElement("button");n.className="jsoneditor-contextmenu",n.title="Click to open the actions menu (Ctrl+M)",e.menu=n,i.appendChild(e.menu)}var r=document.createElement("td"),o=document.createElement("div");return o.innerHTML="(empty)",o.className="jsoneditor-readonly",r.appendChild(o),e.td=r,e.text=o,this.updateDom(),t},t.prototype.updateDom=function(){var e=this.dom,t=e.td;t&&(t.style.paddingLeft=24*this.getLevel()+26+"px");var i=e.text;i&&(i.innerHTML="(empty "+this.parent.type+")");var n=e.tr;this.isVisible()?e.tr.firstChild||(e.tdDrag&&n.appendChild(e.tdDrag),e.tdMenu&&n.appendChild(e.tdMenu),n.appendChild(t)):e.tr.firstChild&&(e.tdDrag&&n.removeChild(e.tdDrag),e.tdMenu&&n.removeChild(e.tdMenu),n.removeChild(t))},t.prototype.isVisible=function(){return 0==this.parent.childs.length},t.prototype.showContextMenu=function(t,i){var n=this,r=e.TYPE_TITLES,s=[{text:"Append",title:"Append a new field with type 'auto' (Ctrl+Shift+Ins)",submenuTitle:"Select the type of the field to be appended",className:"jsoneditor-insert",click:function(){n._onAppend("","","auto")},submenu:[{text:"Auto",className:"jsoneditor-type-auto",title:r.auto,click:function(){n._onAppend("","","auto")}},{text:"Array",className:"jsoneditor-type-array",title:r.array,click:function(){n._onAppend("",[])}},{text:"Object",className:"jsoneditor-type-object",title:r.object,click:function(){n._onAppend("",{})}},{text:"String",className:"jsoneditor-type-string",title:r.string,click:function(){n._onAppend("","","string")}}]}],a=new o(s,{close:i});a.show(t,this.editor.content)},t.prototype.onEvent=function(e){var t=e.type,i=e.target||e.srcElement,n=this.dom,o=n.menu;if(i==o&&("mouseover"==t?this.editor.highlighter.highlight(this.parent):"mouseout"==t&&this.editor.highlighter.unhighlight()),"click"==t&&i==n.menu){var s=this.editor.highlighter;s.highlight(this.parent),s.lock(),r.addClassName(n.menu,"jsoneditor-selected"),this.showContextMenu(n.menu,function(){r.removeClassName(n.menu,"jsoneditor-selected"),s.unlock(),s.unhighlight()})}"keydown"==t&&this.onKeyDown(e)},t}var r=i(54),o=i(57);e.exports=n},function(e,t,i){"use strict";function n(e,t,i,n){for(var o={code:{text:"Code",title:"Switch to code highlighter",click:function(){n("code")}},form:{text:"Form",title:"Switch to form editor",click:function(){n("form")}},text:{text:"Text",title:"Switch to plain text editor",click:function(){n("text")}},tree:{text:"Tree",title:"Switch to tree editor",click:function(){n("tree")}},view:{text:"View",title:"Switch to tree view",click:function(){n("view")}}},s=[],a=0;a0){var o=i.length>l;if(o){i=i.slice(0,l);var a=this.validateSchema.errors.length-l;i.push("("+a+" more errors...)")}var c=document.createElement("div");c.innerHTML=''+i.map(function(e){var t;return t="string"==typeof e?'":"",''+t+""}).join("")+"
'+e+"
"+e.dataPath+""+e.message+"
",this.dom.validationErrors=c,this.frame.appendChild(c);var h=c.clientHeight;this.content.style.marginBottom=-h+"px",this.content.style.paddingBottom=h+"px"}if(this.aceEditor){var d=!1;this.aceEditor.resize(d)}},e.exports=[{mode:"text",mixin:a,data:"text",load:a.format},{mode:"code",mixin:a,data:"text",load:a.format}]},function(e,t,i){var n=i(64);i(67),i(69),i(70),e.exports=n},function(e,t,i){!function(){function e(e){var t=i;e&&(i[e]||(i[e]={}),t=i[e]),t.define&&t.define.packaged||(n.original=t.define,t.define=n,t.define.packaged=!0),t.acequire&&t.acequire.packaged||(o.original=t.acequire,t.acequire=o,t.acequire.packaged=!0)}var t="ace",i=function(){return this}();if(i||"undefined"==typeof window||(i=window),t||"undefined"==typeof acequirejs){var n=function(e,t,i){return"string"!=typeof e?void(n.original?n.original.apply(this,arguments):(console.error("dropping module because define wasn't a string."),console.trace())):(2==arguments.length&&(i=t),void(n.modules[e]||(n.payloads[e]=i,n.modules[e]=null)))};n.modules={},n.payloads={};var r=function(e,t,i){if("string"==typeof t){var n=a(e,t);if(void 0!=n)return i&&i(),n}else if("[object Array]"===Object.prototype.toString.call(t)){for(var r=[],s=0,l=t.length;l>s;++s){var c=a(e,t[s]);if(void 0==c&&o.original)return;r.push(c)}return i&&i.apply(null,r)||!0}},o=function(e,t){var i=r("",e,t);return void 0==i&&o.original?o.original.apply(this,arguments):i},s=function(e,t){if(-1!==t.indexOf("!")){var i=t.split("!");return s(e,i[0])+"!"+s(e,i[1])}if("."==t.charAt(0)){var n=e.split("/").slice(0,-1).join("/");for(t=n+"/"+t;-1!==t.indexOf(".")&&r!=t;){var r=t;t=t.replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return t},a=function(e,t){t=s(e,t);var i=n.modules[t];if(!i){if(i=n.payloads[t],"function"==typeof i){var o={},a={id:t,uri:"",exports:o,packaged:!0},l=function(e,i){return r(t,e,i)},c=i(l,o,a);o=c||a.exports,n.modules[t]=o,delete n.payloads[t]}i=n.modules[t]=o||i}return i};e(t)}}(),ace.define("ace/lib/regexp",["require","exports","module"],function(e,t,i){"use strict";function n(e){return(e.global?"g":"")+(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":"")}function r(e,t,i){if(Array.prototype.indexOf)return e.indexOf(t,i);for(var n=i||0;n1&&r(l,"")>-1&&(i=RegExp(this.source,o.replace.call(n(this),"g","")),o.replace.call(e.slice(l.index),i,function(){for(var e=1;el.index&&this.lastIndex--}return l},a||(RegExp.prototype.test=function(e){var t=o.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t}))}),ace.define("ace/lib/es5-shim",["require","exports","module"],function(e,t,i){function n(){}function r(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function o(e){return e=+e,e!==e?e=0:0!==e&&e!==1/0&&e!==-(1/0)&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}Function.prototype.bind||(Function.prototype.bind=function(e){var t=this;if("function"!=typeof t)throw new TypeError("Function.prototype.bind called on incompatible "+t);var i=p.call(arguments,1),r=function(){if(this instanceof r){var n=t.apply(this,i.concat(p.call(arguments)));return Object(n)===n?n:this}return t.apply(e,i.concat(p.call(arguments)))};return t.prototype&&(n.prototype=t.prototype,r.prototype=new n,n.prototype=null),r});var s,a,l,c,h,d=Function.prototype.call,u=Array.prototype,f=Object.prototype,p=u.slice,m=d.bind(f.toString),g=d.bind(f.hasOwnProperty);if((h=g(f,"__defineGetter__"))&&(s=d.bind(f.__defineGetter__),a=d.bind(f.__defineSetter__),l=d.bind(f.__lookupGetter__),c=d.bind(f.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t,i=[];return i.splice.apply(i,e(20)),i.splice.apply(i,e(26)),t=i.length,i.splice(5,0,"XXX"),t+1==i.length,t+1==i.length?!0:void 0}()){var v=Array.prototype.splice;Array.prototype.splice=function(e,t){return arguments.length?v.apply(this,[void 0===e?0:e,void 0===t?this.length-e:t].concat(p.call(arguments,2))):[]}}else Array.prototype.splice=function(e,t){var i=this.length;e>0?e>i&&(e=i):void 0==e?e=0:0>e&&(e=Math.max(i+e,0)),i>e+t||(t=i-e);var n=this.slice(e,e+t),r=p.call(arguments,2),o=r.length;if(e===i)o&&this.push.apply(this,r);else{var s=Math.min(t,i-e),a=e+s,l=a+o-s,c=i-a,h=i-s;if(a>l)for(var d=0;c>d;++d)this[l+d]=this[a+d];else if(l>a)for(d=c;d--;)this[l+d]=this[a+d];if(o&&e===h)this.length=h,this.push.apply(this,r);else for(this.length=h+o,d=0;o>d;++d)this[e+d]=r[d]}return n};Array.isArray||(Array.isArray=function(e){return"[object Array]"==m(e)});var w=Object("a"),y="a"!=w[0]||!(0 in w);if(Array.prototype.forEach||(Array.prototype.forEach=function(e){var t=M(this),i=y&&"[object String]"==m(this)?this.split(""):t,n=arguments[1],r=-1,o=i.length>>>0;if("[object Function]"!=m(e))throw new TypeError;for(;++r>>0,r=Array(n),o=arguments[1];if("[object Function]"!=m(e))throw new TypeError(e+" is not a function");for(var s=0;n>s;s++)s in i&&(r[s]=e.call(o,i[s],s,t));return r}),Array.prototype.filter||(Array.prototype.filter=function(e){var t,i=M(this),n=y&&"[object String]"==m(this)?this.split(""):i,r=n.length>>>0,o=[],s=arguments[1];if("[object Function]"!=m(e))throw new TypeError(e+" is not a function");for(var a=0;r>a;a++)a in n&&(t=n[a],e.call(s,t,a,i)&&o.push(t));return o}),Array.prototype.every||(Array.prototype.every=function(e){var t=M(this),i=y&&"[object String]"==m(this)?this.split(""):t,n=i.length>>>0,r=arguments[1];if("[object Function]"!=m(e))throw new TypeError(e+" is not a function");for(var o=0;n>o;o++)if(o in i&&!e.call(r,i[o],o,t))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(e){var t=M(this),i=y&&"[object String]"==m(this)?this.split(""):t,n=i.length>>>0,r=arguments[1];if("[object Function]"!=m(e))throw new TypeError(e+" is not a function");for(var o=0;n>o;o++)if(o in i&&e.call(r,i[o],o,t))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(e){var t=M(this),i=y&&"[object String]"==m(this)?this.split(""):t,n=i.length>>>0;if("[object Function]"!=m(e))throw new TypeError(e+" is not a function");if(!n&&1==arguments.length)throw new TypeError("reduce of empty array with no initial value");var r,o=0;if(arguments.length>=2)r=arguments[1];else for(;;){if(o in i){r=i[o++];break}if(++o>=n)throw new TypeError("reduce of empty array with no initial value")}for(;n>o;o++)o in i&&(r=e.call(void 0,r,i[o],o,t));return r}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(e){var t=M(this),i=y&&"[object String]"==m(this)?this.split(""):t,n=i.length>>>0;if("[object Function]"!=m(e))throw new TypeError(e+" is not a function");if(!n&&1==arguments.length)throw new TypeError("reduceRight of empty array with no initial value");var r,o=n-1;if(arguments.length>=2)r=arguments[1];else for(;;){if(o in i){r=i[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}do o in this&&(r=e.call(void 0,r,i[o],o,t));while(o--);return r}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(e){var t=y&&"[object String]"==m(this)?this.split(""):M(this),i=t.length>>>0;if(!i)return-1;var n=0;for(arguments.length>1&&(n=o(arguments[1])),n=n>=0?n:Math.max(0,i+n);i>n;n++)if(n in t&&t[n]===e)return n;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(e){var t=y&&"[object String]"==m(this)?this.split(""):M(this),i=t.length>>>0;if(!i)return-1;var n=i-1;for(arguments.length>1&&(n=Math.min(n,o(arguments[1]))),n=n>=0?n:i-Math.abs(n);n>=0;n--)if(n in t&&e===t[n])return n;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(e){return e.__proto__||(e.constructor?e.constructor.prototype:f)}),!Object.getOwnPropertyDescriptor){var A="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(e,t){if("object"!=typeof e&&"function"!=typeof e||null===e)throw new TypeError(A+e);if(g(e,t)){var i,n,r;if(i={enumerable:!0,configurable:!0},h){var o=e.__proto__;e.__proto__=f;var n=l(e,t),r=c(e,t);if(e.__proto__=o,n||r)return n&&(i.get=n),r&&(i.set=r),i}return i.value=e[t],i}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(e){return Object.keys(e)}),!Object.create){var C;C=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(e,t){var i;if(null===e)i=C();else{if("object"!=typeof e)throw new TypeError("typeof prototype["+typeof e+"] != 'object'");var n=function(){};n.prototype=e,i=new n,i.__proto__=e}return void 0!==t&&Object.defineProperties(i,t),i}}if(Object.defineProperty){var E=r({}),b="undefined"==typeof document||r(document.createElement("div"));if(!E||!b)var F=Object.defineProperty}if(!Object.defineProperty||F){var x="Property description must be an object: ",S="Object.defineProperty called on non-object: ",$="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(e,t,i){if("object"!=typeof e&&"function"!=typeof e||null===e)throw new TypeError(S+e);if("object"!=typeof i&&"function"!=typeof i||null===i)throw new TypeError(x+i);if(F)try{return F.call(Object,e,t,i)}catch(n){}if(g(i,"value"))if(h&&(l(e,t)||c(e,t))){var r=e.__proto__;e.__proto__=f,delete e[t],e[t]=i.value,e.__proto__=r}else e[t]=i.value;else{if(!h)throw new TypeError($);g(i,"get")&&s(e,t,i.get),g(i,"set")&&a(e,t,i.set)}return e}}Object.defineProperties||(Object.defineProperties=function(e,t){for(var i in t)g(t,i)&&Object.defineProperty(e,i,t[i]);return e}),Object.seal||(Object.seal=function(e){return e}),Object.freeze||(Object.freeze=function(e){return e});try{Object.freeze(function(){})}catch(D){Object.freeze=function(e){return function(t){return"function"==typeof t?t:e(t)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(e){return e}),Object.isSealed||(Object.isSealed=function(e){return!1}),Object.isFrozen||(Object.isFrozen=function(e){return!1}),Object.isExtensible||(Object.isExtensible=function(e){if(Object(e)===e)throw new TypeError;for(var t="";g(e,t);)t+="?";e[t]=!0;var i=g(e,t);return delete e[t],i}),!Object.keys){var k=!0,B=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],_=B.length;for(var L in{toString:null})k=!1;Object.keys=function O(e){if("object"!=typeof e&&"function"!=typeof e||null===e)throw new TypeError("Object.keys called on a non-object");var O=[];for(var t in e)g(e,t)&&O.push(t);if(k)for(var i=0,n=_;n>i;i++){var r=B[i];g(e,r)&&O.push(r)}return O}}Date.now||(Date.now=function(){return(new Date).getTime()});var R=" \n\x0B\f\r   ᠎              \u2028\u2029\ufeff";if(!String.prototype.trim||R.trim()){R="["+R+"]";var T=new RegExp("^"+R+R+"*"),P=new RegExp(R+R+"*$");String.prototype.trim=function(){return String(this).replace(T,"").replace(P,"")}}var M=function(e){if(null==e)throw new TypeError("can't convert "+e+" to object");return Object(e)}}),ace.define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"],function(e,t,i){"use strict";e("./regexp"),e("./es5-shim")}),ace.define("ace/lib/dom",["require","exports","module"],function(e,t,i){"use strict";var n="http://www.w3.org/1999/xhtml";return t.getDocumentHead=function(e){return e||(e=document),e.head||e.getElementsByTagName("head")[0]||e.documentElement},t.createElement=function(e,t){return document.createElementNS?document.createElementNS(t||n,e):document.createElement(e)},t.hasCssClass=function(e,t){var i=(e.className||"").split(/\s+/g);return-1!==i.indexOf(t)},t.addCssClass=function(e,i){t.hasCssClass(e,i)||(e.className+=" "+i)},t.removeCssClass=function(e,t){for(var i=e.className.split(/\s+/g);;){var n=i.indexOf(t);if(-1==n)break;i.splice(n,1)}e.className=i.join(" ")},t.toggleCssClass=function(e,t){for(var i=e.className.split(/\s+/g),n=!0;;){var r=i.indexOf(t);if(-1==r)break;n=!1,i.splice(r,1)}return n&&i.push(t),e.className=i.join(" "),n},t.setCssClass=function(e,i,n){n?t.addCssClass(e,i):t.removeCssClass(e,i)},t.hasCssString=function(e,t){var i,n=0;if(t=t||document,t.createStyleSheet&&(i=t.styleSheets)){for(;n=0?parseFloat((r.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]):parseFloat((r.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=(window.Controllers||window.controllers)&&"Gecko"===window.navigator.product,t.isOldGecko=t.isGecko&&parseInt((r.match(/rv\:(\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&"[object Opera]"==Object.prototype.toString.call(window.opera),t.isWebKit=parseFloat(r.split("WebKit/")[1])||void 0,t.isChrome=parseFloat(r.split(" Chrome/")[1])||void 0,t.isAIR=r.indexOf("AdobeAIR")>=0,t.isIPad=r.indexOf("iPad")>=0,t.isTouchPad=r.indexOf("TouchPad")>=0,t.isChromeOS=r.indexOf(" CrOS ")>=0}}),ace.define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,i){"use strict";function n(e,t,i){var n=c(t);if(!s.isMac&&a){if(a.OSKey&&(n|=8),a.altGr){if(3==(3&n))return;a.altGr=0}if(18===i||17===i){var r="location"in t?t.location:t.keyLocation;if(17===i&&1===r)1==a[i]&&(l=t.timeStamp);else if(18===i&&3===n&&2===r){var h=t.timeStamp-l;50>h&&(a.altGr=!0)}}}if(i in o.MODIFIER_KEYS&&(i=-1),8&n&&i>=91&&93>=i&&(i=-1),!n&&13===i){var r="location"in t?t.location:t.keyLocation;if(3===r&&(e(t,n,-i),t.defaultPrevented))return}if(s.isChromeOS&&8&n){if(e(t,n,i),t.defaultPrevented)return;n&=-9}return n||i in o.FUNCTION_KEYS||i in o.PRINTABLE_KEYS?e(t,n,i):!1}function r(){a=Object.create(null),a.count=0,a.lastT=0}var o=e("./keys"),s=e("./useragent"),a=null,l=0; +t.addListener=function(e,t,i){if(e.addEventListener)return e.addEventListener(t,i,!1);if(e.attachEvent){var n=function(){i.call(e,window.event)};i._wrapper=n,e.attachEvent("on"+t,n)}},t.removeListener=function(e,t,i){return e.removeEventListener?e.removeEventListener(t,i,!1):void(e.detachEvent&&e.detachEvent("on"+t,i._wrapper||i))},t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},t.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},t.getButton=function(e){return"dblclick"==e.type?0:"contextmenu"==e.type||s.isMac&&e.ctrlKey&&!e.altKey&&!e.shiftKey?2:e.preventDefault?e.button:{1:0,2:2,4:1}[e.button]},t.capture=function(e,i,n){function r(e){i&&i(e),n&&n(e),t.removeListener(document,"mousemove",i,!0),t.removeListener(document,"mouseup",r,!0),t.removeListener(document,"dragstart",r,!0)}return t.addListener(document,"mousemove",i,!0),t.addListener(document,"mouseup",r,!0),t.addListener(document,"dragstart",r,!0),r},t.addTouchMoveListener=function(e,i){if("ontouchmove"in e){var n,r;t.addListener(e,"touchstart",function(e){var t=e.changedTouches[0];n=t.clientX,r=t.clientY}),t.addListener(e,"touchmove",function(e){var t=1,o=e.changedTouches[0];e.wheelX=-(o.clientX-n)/t,e.wheelY=-(o.clientY-r)/t,n=o.clientX,r=o.clientY,i(e)})}},t.addMouseWheelListener=function(e,i){"onmousewheel"in e?t.addListener(e,"mousewheel",function(e){var t=8;void 0!==e.wheelDeltaX?(e.wheelX=-e.wheelDeltaX/t,e.wheelY=-e.wheelDeltaY/t):(e.wheelX=0,e.wheelY=-e.wheelDelta/t),i(e)}):"onwheel"in e?t.addListener(e,"wheel",function(e){var t=.35;switch(e.deltaMode){case e.DOM_DELTA_PIXEL:e.wheelX=e.deltaX*t||0,e.wheelY=e.deltaY*t||0;break;case e.DOM_DELTA_LINE:case e.DOM_DELTA_PAGE:e.wheelX=5*(e.deltaX||0),e.wheelY=5*(e.deltaY||0)}i(e)}):t.addListener(e,"DOMMouseScroll",function(e){e.axis&&e.axis==e.HORIZONTAL_AXIS?(e.wheelX=5*(e.detail||0),e.wheelY=0):(e.wheelX=0,e.wheelY=5*(e.detail||0)),i(e)})},t.addMultiMouseDownListener=function(e,i,n,r){function o(e){if(0!==t.getButton(e)?d=0:e.detail>1?(d++,d>4&&(d=1)):d=1,s.isIE){var o=Math.abs(e.clientX-l)>5||Math.abs(e.clientY-c)>5;h&&!o||(d=1),h&&clearTimeout(h),h=setTimeout(function(){h=null},i[d-1]||600),1==d&&(l=e.clientX,c=e.clientY)}if(e._clicks=d,n[r]("mousedown",e),d>4)d=0;else if(d>1)return n[r](u[d],e)}function a(e){d=2,h&&clearTimeout(h),h=setTimeout(function(){h=null},i[d-1]||600),n[r]("mousedown",e),n[r](u[d],e)}var l,c,h,d=0,u={2:"dblclick",3:"tripleclick",4:"quadclick"};Array.isArray(e)||(e=[e]),e.forEach(function(e){t.addListener(e,"mousedown",o),s.isOldIE&&t.addListener(e,"dblclick",a)})};var c=!s.isMac||!s.isOpera||"KeyboardEvent"in window?function(e){return 0|(e.ctrlKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.metaKey?8:0)}:function(e){return 0|(e.metaKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.ctrlKey?8:0)};if(t.getModifierString=function(e){return o.KEY_MODS[c(e)]},t.addCommandKeyListener=function(e,i){var o=t.addListener;if(s.isOldGecko||s.isOpera&&!("KeyboardEvent"in window)){var l=null;o(e,"keydown",function(e){l=e.keyCode}),o(e,"keypress",function(e){return n(i,e,l)})}else{var c=null;o(e,"keydown",function(e){var t=e.keyCode;a[t]=(a[t]||0)+1,91==t||92==t?a.OSKey=!0:a.OSKey&&e.timeStamp-a.lastT>200&&1==a.count&&r(),1==a[t]&&a.count++,a.lastT=e.timeStamp;var o=n(i,e,t);return c=e.defaultPrevented,o}),o(e,"keypress",function(e){c&&(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey)&&(t.stopEvent(e),c=null)}),o(e,"keyup",function(e){var t=e.keyCode;a[t]?a.count=Math.max(a.count-1,0):r(),91!=t&&92!=t||(a.OSKey=!1),a[t]=null}),a||(r(),o(window,"focus",r))}},"object"==typeof window&&window.postMessage&&!s.isOldIE){var h=1;t.nextTick=function(e,i){i=i||window;var n="zero-timeout-message-"+h;t.addListener(i,"message",function r(o){o.data==n&&(t.stopPropagation(o),t.removeListener(i,"message",r),e())}),i.postMessage(n,"*")}}t.nextFrame="object"==typeof window&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),ace.define("ace/lib/lang",["require","exports","module"],function(e,t,i){"use strict";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){for(var i="";t>0;)1&t&&(i+=e),(t>>=1)&&(e+=e);return i};var n=/^\s\s*/,r=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(n,"")},t.stringTrimRight=function(e){return e.replace(r,"")},t.copyObject=function(e){var t={};for(var i in e)t[i]=e[i];return t},t.copyArray=function(e){for(var t=[],i=0,n=e.length;n>i;i++)e[i]&&"object"==typeof e[i]?t[i]=this.copyObject(e[i]):t[i]=e[i];return t},t.deepCopy=function o(e){if("object"!=typeof e||!e)return e;var t;if(Array.isArray(e)){t=[];for(var i=0;ii?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var s=(e("../lib/dom"),e("../lib/event"),e("../lib/useragent"),0);(function(){this.onMouseDown=function(e){var t=e.inSelection(),i=e.getDocumentPosition();this.mousedownEvent=e;var n=this.editor,r=e.getButton();if(0!==r){var o=n.getSelectionRange(),s=o.isEmpty();return n.$blockScrolling++,(s||1==r)&&n.selection.moveToPosition(i),n.$blockScrolling--,void(2==r&&n.textInput.onContextMenu(e.domEvent))}return this.mousedownEvent.time=Date.now(),!t||n.isFocused()||(n.focus(),!this.$focusTimout||this.$clickSelection||n.inMultiSelectMode)?(this.captureMouse(e),this.startSelect(i,e.domEvent._clicks>1),e.preventDefault()):(this.setState("focusWait"),void this.captureMouse(e))},this.startSelect=function(e,t){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var i=this.editor;i.$blockScrolling++,this.mousedownEvent.getShiftKey()?i.selection.selectToPosition(e):t||i.selection.moveToPosition(e),t||this.select(),i.renderer.scroller.setCapture&&i.renderer.scroller.setCapture(),i.setStyle("ace_selecting"),this.setState("select"),i.$blockScrolling--},this.select=function(){var e,t=this.editor,i=t.renderer.screenToTextCoordinates(this.x,this.y);if(t.$blockScrolling++,this.$clickSelection){var n=this.$clickSelection.comparePoint(i);if(-1==n)e=this.$clickSelection.end;else if(1==n)e=this.$clickSelection.start;else{var r=o(this.$clickSelection,i);i=r.cursor,e=r.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(i),t.$blockScrolling--,t.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(e){var t,i=this.editor,n=i.renderer.screenToTextCoordinates(this.x,this.y),r=i.selection[e](n.row,n.column);if(i.$blockScrolling++,this.$clickSelection){var s=this.$clickSelection.comparePoint(r.start),a=this.$clickSelection.comparePoint(r.end);if(-1==s&&0>=a)t=this.$clickSelection.end,r.end.row==n.row&&r.end.column==n.column||(n=r.start);else if(1==a&&s>=0)t=this.$clickSelection.start,r.start.row==n.row&&r.start.column==n.column||(n=r.end);else if(-1==s&&1==a)n=r.end,t=r.start;else{var l=o(this.$clickSelection,n);n=l.cursor,t=l.anchor}i.selection.setSelectionAnchor(t.row,t.column)}i.selection.selectToPosition(n),i.$blockScrolling--,i.renderer.scrollCursorIntoView()},this.selectEnd=this.selectAllEnd=this.selectByWordsEnd=this.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle("ace_selecting"),this.editor.renderer.scroller.releaseCapture&&this.editor.renderer.scroller.releaseCapture()},this.focusWait=function(){var e=r(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=Date.now();(e>s||t-this.mousedownEvent.time>this.$focusTimout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),i=this.editor,n=i.session,r=n.getBracketRange(t);r?(r.isEmpty()&&(r.start.column--,r.end.column++),this.setState("select")):(r=i.selection.getWordRange(t.row,t.column),this.setState("selectByWords")),this.$clickSelection=r,this.select()},this.onTripleClick=function(e){var t=e.getDocumentPosition(),i=this.editor;this.setState("selectByLines");var n=i.getSelectionRange();n.isMultiLine()&&n.contains(t.row,t.column)?(this.$clickSelection=i.selection.getLineRange(n.start.row),this.$clickSelection.end=i.selection.getLineRange(n.end.row).end):this.$clickSelection=i.selection.getLineRange(t.row),this.select()},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("selectAll")},this.onMouseWheel=function(e){if(!e.getAccelKey()){e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=e.domEvent.timeStamp,i=t-(this.$lastScrollTime||0),n=this.editor,r=n.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);return r||200>i?(this.$lastScrollTime=t,n.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()):void 0}},this.onTouchMove=function(e){var t=e.domEvent.timeStamp,i=t-(this.$lastScrollTime||0),n=this.editor,r=n.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);return r||200>i?(this.$lastScrollTime=t,n.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()):void 0}}).call(n.prototype),t.DefaultHandlers=n}),ace.define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"],function(e,t,i){"use strict";function n(e){this.isOpen=!1,this.$element=null,this.$parentNode=e}var r=(e("./lib/oop"),e("./lib/dom"));(function(){this.$init=function(){return this.$element=r.createElement("div"),this.$element.className="ace_tooltip",this.$element.style.display="none",this.$parentNode.appendChild(this.$element),this.$element},this.getElement=function(){return this.$element||this.$init()},this.setText=function(e){r.setInnerText(this.getElement(),e)},this.setHtml=function(e){this.getElement().innerHTML=e},this.setPosition=function(e,t){this.getElement().style.left=e+"px",this.getElement().style.top=t+"px"},this.setClassName=function(e){r.addCssClass(this.getElement(),e)},this.show=function(e,t,i){null!=e&&this.setText(e),null!=t&&null!=i&&this.setPosition(t,i),this.isOpen||(this.getElement().style.display="block",this.isOpen=!0)},this.hide=function(){this.isOpen&&(this.getElement().style.display="none",this.isOpen=!1)},this.getHeight=function(){return this.getElement().offsetHeight},this.getWidth=function(){return this.getElement().offsetWidth}}).call(n.prototype),t.Tooltip=n}),ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"],function(e,t,i){"use strict";function n(e){function t(){var t=d.getDocumentPosition().row,r=l.$annotations[t];if(!r)return i();var o=s.session.getLength();if(t==o){var a=s.renderer.pixelToScreenCoordinates(0,d.y).row,h=d.$pos;if(a>s.session.documentToScreenRow(h.row,h.column))return i()}if(u!=r)if(u=r.text.join("
"),c.setHtml(u),c.show(),s.on("mousewheel",i),e.$tooltipFollowsMouse)n(d);else{var f=d.domEvent.target,p=f.getBoundingClientRect(),m=c.getElement().style;m.left=p.right+"px",m.top=p.bottom+"px"}}function i(){h&&(h=clearTimeout(h)),u&&(c.hide(),u=null,s.removeEventListener("mousewheel",i))}function n(e){c.setPosition(e.x,e.y)}var s=e.editor,l=s.renderer.$gutterLayer,c=new r(s.container);e.editor.setDefaultHandler("guttermousedown",function(t){if(s.isFocused()&&0==t.getButton()){var i=l.getRegion(t);if("foldWidgets"!=i){var n=t.getDocumentPosition().row,r=s.session.selection;if(t.getShiftKey())r.selectTo(n,0);else{if(2==t.domEvent.detail)return s.selectAll(),t.preventDefault();e.$clickSelection=s.selection.getLineRange(n)}return e.setState("selectByLines"),e.captureMouse(t),t.preventDefault()}}});var h,d,u;e.editor.setDefaultHandler("guttermousemove",function(r){var s=r.domEvent.target||r.domEvent.srcElement;return o.hasCssClass(s,"ace_fold-widget")?i():(u&&e.$tooltipFollowsMouse&&n(r),d=r,void(h||(h=setTimeout(function(){h=null,d&&!e.isMousePressed?t():i()},50))))}),a.addListener(s.renderer.$gutter,"mouseout",function(e){d=null,u&&!h&&(h=setTimeout(function(){h=null,i()},50))}),s.on("changeSession",i)}function r(e){l.call(this,e)}var o=e("../lib/dom"),s=e("../lib/oop"),a=e("../lib/event"),l=e("../tooltip").Tooltip;s.inherits(r,l),function(){this.setPosition=function(e,t){var i=window.innerWidth||document.documentElement.clientWidth,n=window.innerHeight||document.documentElement.clientHeight,r=this.getWidth(),o=this.getHeight();e+=15,t+=15,e+r>i&&(e-=e+r-i),t+o>n&&(t-=20+o),l.prototype.setPosition.call(this,e,t)}}.call(r.prototype),t.GutterHandler=n}),ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,t,i){"use strict";var n=e("../lib/event"),r=e("../lib/useragent"),o=t.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){n.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){n.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(null!==this.$inSelection)return this.$inSelection;var e=this.editor,t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var i=this.getDocumentPosition();this.$inSelection=t.contains(i.row,i.column)}return this.$inSelection},this.getButton=function(){return n.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=r.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(o.prototype)}),ace.define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,t,i){"use strict";function n(e){function t(e,t){var i=Date.now(),n=!t||e.row!=t.row,o=!t||e.column!=t.column;if(!D||n||o)g.$blockScrolling+=1,g.moveCursorToPosition(e),g.$blockScrolling-=1,D=i,k={x:A,y:C};else{var s=r(k.x,k.y,A,C);s>h?D=null:i-D>=c&&(g.renderer.scrollCursorIntoView(),D=null)}}function i(e,t){var i=Date.now(),n=g.renderer.layerConfig.lineHeight,r=g.renderer.layerConfig.characterWidth,o=g.renderer.scroller.getBoundingClientRect(),s={x:{left:A-o.left,right:o.right-A},y:{top:C-o.top,bottom:o.bottom-C}},a=Math.min(s.x.left,s.x.right),c=Math.min(s.y.top,s.y.bottom),h={row:e.row,column:e.column};2>=a/r&&(h.column+=s.x.left=c/n&&(h.row+=s.y.top=l&&g.renderer.scrollCursorIntoView(h):$=i:$=null}function n(){var e=F;F=g.renderer.screenToTextCoordinates(A,C),t(F,e),i(F,e)}function d(){b=g.selection.toOrientedRange(),y=g.session.addMarker(b,"ace_selection",g.getSelectionStyle()),g.clearSelection(),g.isFocused()&&g.renderer.$cursorLayer.setBlinking(!1),clearInterval(E),n(),E=setInterval(n,20),_=0,s.addListener(document,"mousemove",f)}function u(){clearInterval(E),g.session.removeMarker(y),y=null,g.$blockScrolling+=1,g.selection.fromOrientedRange(b),g.$blockScrolling-=1,g.isFocused()&&!S&&g.renderer.$cursorLayer.setBlinking(!g.getReadOnly()),b=null,F=null,_=0,$=null,D=null,s.removeListener(document,"mousemove",f)}function f(){null==L&&(L=setTimeout(function(){null!=L&&y&&u()},20))}function p(e){var t=e.types;return!t||Array.prototype.some.call(t,function(e){return"text/plain"==e||"Text"==e})}function m(e){var t=["copy","copymove","all","uninitialized"],i=["move","copymove","linkmove","all","uninitialized"],n=a.isMac?e.altKey:e.ctrlKey,r="uninitialized";try{r=e.dataTransfer.effectAllowed.toLowerCase()}catch(e){}var o="none";return n&&t.indexOf(r)>=0?o="copy":i.indexOf(r)>=0?o="move":t.indexOf(r)>=0&&(o="copy"),o}var g=e.editor,v=o.createElement("img");v.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",a.isOpera&&(v.style.cssText="width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;");var w=["dragWait","dragWaitEnd","startDrag","dragReadyEnd","onMouseDrag"];w.forEach(function(t){e[t]=this[t]},this),g.addEventListener("mousedown",this.onMouseDown.bind(e));var y,A,C,E,b,F,x,S,$,D,k,B=g.container,_=0;this.onDragStart=function(e){if(this.cancelDrag||!B.draggable){var t=this;return setTimeout(function(){t.startSelect(),t.captureMouse(e)},0),e.preventDefault()}b=g.getSelectionRange();var i=e.dataTransfer;i.effectAllowed=g.getReadOnly()?"copy":"copyMove",a.isOpera&&(g.container.appendChild(v),v.scrollTop=0),i.setDragImage&&i.setDragImage(v,0,0),a.isOpera&&g.container.removeChild(v),i.clearData(),i.setData("Text",g.session.getTextRange()),S=!0,this.setState("drag")},this.onDragEnd=function(e){if(B.draggable=!1,S=!1,this.setState(null),!g.getReadOnly()){var t=e.dataTransfer.dropEffect;x||"move"!=t||g.session.remove(g.getSelectionRange()),g.renderer.$cursorLayer.setBlinking(!0)}this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle("")},this.onDragEnter=function(e){return!g.getReadOnly()&&p(e.dataTransfer)?(A=e.clientX,C=e.clientY,y||d(),_++,e.dataTransfer.dropEffect=x=m(e),s.preventDefault(e)):void 0},this.onDragOver=function(e){return!g.getReadOnly()&&p(e.dataTransfer)?(A=e.clientX,C=e.clientY,y||(d(),_++),null!==L&&(L=null),e.dataTransfer.dropEffect=x=m(e),s.preventDefault(e)):void 0},this.onDragLeave=function(e){return _--,0>=_&&y?(u(),x=null,s.preventDefault(e)):void 0},this.onDrop=function(e){if(F){var t=e.dataTransfer;if(S)switch(x){case"move":b=b.contains(F.row,F.column)?{start:F,end:F}:g.moveText(b,F);break;case"copy":b=g.moveText(b,F,!0)}else{var i=t.getData("Text");b={start:F,end:g.session.insert(F,i)},g.focus(),x=null}return u(),s.preventDefault(e)}},s.addListener(B,"dragstart",this.onDragStart.bind(e)),s.addListener(B,"dragend",this.onDragEnd.bind(e)),s.addListener(B,"dragenter",this.onDragEnter.bind(e)),s.addListener(B,"dragover",this.onDragOver.bind(e)),s.addListener(B,"dragleave",this.onDragLeave.bind(e)),s.addListener(B,"drop",this.onDrop.bind(e));var L=null}function r(e,t,i,n){return Math.sqrt(Math.pow(i-e,2)+Math.pow(n-t,2))}var o=e("../lib/dom"),s=e("../lib/event"),a=e("../lib/useragent"),l=200,c=200,h=5;(function(){this.dragWait=function(){var e=Date.now()-this.mousedownEvent.time;e>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var e=this.editor.container;e.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()),this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle(""),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var e=this.editor,t=e.container;t.draggable=!0,e.renderer.$cursorLayer.setBlinking(!1),e.setStyle("ace_dragging");var i=a.isWin?"default":"move";e.renderer.setCursorStyle(i),this.setState("dragReady")},this.onMouseDrag=function(e){var t=this.editor.container;if(a.isIE&&"dragReady"==this.state){var i=r(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);i>3&&t.dragDrop()}if("dragWait"===this.state){var i=r(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);i>0&&(t.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(e){if(this.$dragEnabled){this.mousedownEvent=e;var t=this.editor,i=e.inSelection(),n=e.getButton(),r=e.domEvent.detail||1;if(1===r&&0===n&&i){if(e.editor.inMultiSelectMode&&(e.getAccelKey()||e.getShiftKey()))return;this.mousedownEvent.time=Date.now();var o=e.domEvent.target||e.domEvent.srcElement;if("unselectable"in o&&(o.unselectable="on"),t.getDragDelay()){if(a.isWebKit){this.cancelDrag=!0;var s=t.container;s.draggable=!0}this.setState("dragWait")}else this.startDrag();this.captureMouse(e,this.onMouseDrag.bind(this)),e.defaultPrevented=!0}}}}).call(n.prototype),t.DragdropHandler=n}),ace.define("ace/lib/net",["require","exports","module","ace/lib/dom"],function(e,t,i){"use strict";var n=e("./dom");t.get=function(e,t){var i=new XMLHttpRequest;i.open("GET",e,!0),i.onreadystatechange=function(){4===i.readyState&&t(i.responseText)},i.send(null)},t.loadScript=function(e,t){var i=n.getDocumentHead(),r=document.createElement("script");r.src=e,i.appendChild(r),r.onload=r.onreadystatechange=function(e,i){!i&&r.readyState&&"loaded"!=r.readyState&&"complete"!=r.readyState||(r=r.onload=r.onreadystatechange=null,i||t())}},t.qualifyURL=function(e){var t=document.createElement("a");return t.href=e,t.href}}),ace.define("ace/lib/event_emitter",["require","exports","module"],function(e,t,i){"use strict";var n={},r=function(){this.propagationStopped=!0},o=function(){this.defaultPrevented=!0};n._emit=n._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var i=this._eventRegistry[e]||[],n=this._defaultHandlers[e];if(i.length||n){"object"==typeof t&&t||(t={}),t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=r),t.preventDefault||(t.preventDefault=o),i=i.slice();for(var s=0;sv;v++){var y=g[v];0===y.name.indexOf("data-ace-")&&(s[o(y.name.replace(/^data-ace-/,""))]=y.value)}var A=m.match(/^(.*)\/ace(\-\w+)?\.js(\?|$)/);A&&(a=A[1])}}a&&(s.base=s.base||a,s.packaged=!0),s.basePath=s.base,s.workerPath=s.workerPath||s.base,s.modePath=s.modePath||s.base,s.themePath=s.themePath||s.base,delete s.base;for(var C in s)"undefined"!=typeof s[C]&&t.set(C,s[C])}}function o(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}var s=e("./lib/lang"),a=(e("./lib/oop"),e("./lib/net")),l=e("./lib/app_config").AppConfig;n.exports=t=new l;var c=function(){return this||"undefined"!=typeof window&&window}(),h={packaged:!1,workerPath:null,modePath:null,themePath:null,basePath:"",suffix:".js",$moduleUrls:{}};t.get=function(e){if(!h.hasOwnProperty(e))throw new Error("Unknown config key: "+e);return h[e]},t.set=function(e,t){if(!h.hasOwnProperty(e))throw new Error("Unknown config key: "+e);h[e]=t},t.all=function(){return s.copyObject(h)},t.moduleUrl=function(e,t){if(h.$moduleUrls[e])return h.$moduleUrls[e];var i=e.split("/");t=t||i[i.length-2]||"";var n="snippets"==t?"/":"-",r=i[i.length-1];if("worker"==t&&"-"==n){var o=new RegExp("^"+t+"[\\-_]|[\\-_]"+t+"$","g");r=r.replace(o,"")}(!r||r==t)&&i.length>1&&(r=i[i.length-2]);var s=h[t+"Path"];return null==s?s=h.basePath:"/"==n&&(t=n=""),s&&"/"!=s.slice(-1)&&(s+="/"),s+t+n+r+this.get("suffix")},t.setModuleUrl=function(e,t){return h.$moduleUrls[e]=t},t.$loading={},t.loadModule=function(i,n){var r,o;Array.isArray(i)&&(o=i[0],i=i[1]);try{r=e(i)}catch(s){}if(r&&!t.$loading[i])return n&&n(r);if(t.$loading[i]||(t.$loading[i]=[]),t.$loading[i].push(n),!(t.$loading[i].length>1)){var l=function(){e([i],function(e){t._emit("load.module",{name:i,module:e});var n=t.$loading[i];t.$loading[i]=null,n.forEach(function(t){t&&t(e)})})};return t.get("packaged")?void a.loadScript(t.moduleUrl(i,o),l):l()}},r(!0),t.init=r}),ace.define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event","ace/mouse/dragdrop_handler","ace/config"],function(e,t,i){"use strict";var n=e("../lib/event"),r=e("../lib/useragent"),o=e("./default_handlers").DefaultHandlers,s=e("./default_gutter_handler").GutterHandler,a=e("./mouse_event").MouseEvent,l=e("./dragdrop_handler").DragdropHandler,c=e("../config"),h=function(e){var t=this;this.editor=e,new o(this),new s(this),new l(this);var i=function(t){var i=!document.hasFocus||!document.hasFocus()||!e.isFocused()&&document.activeElement==(e.textInput&&e.textInput.getElement());i&&window.focus(),e.focus()},a=e.renderer.getMouseEventTarget();n.addListener(a,"click",this.onMouseEvent.bind(this,"click")),n.addListener(a,"mousemove",this.onMouseMove.bind(this,"mousemove")),n.addMultiMouseDownListener([a,e.renderer.scrollBarV&&e.renderer.scrollBarV.inner,e.renderer.scrollBarH&&e.renderer.scrollBarH.inner,e.textInput&&e.textInput.getElement()].filter(Boolean),[400,300,250],this,"onMouseEvent"),n.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,"mousewheel")),n.addTouchMoveListener(e.container,this.onTouchMove.bind(this,"touchmove"));var c=e.renderer.$gutter;n.addListener(c,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),n.addListener(c,"click",this.onMouseEvent.bind(this,"gutterclick")),n.addListener(c,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),n.addListener(c,"mousemove",this.onMouseEvent.bind(this,"guttermousemove")),n.addListener(a,"mousedown",i),n.addListener(c,"mousedown",i),r.isIE&&e.renderer.scrollBarV&&(n.addListener(e.renderer.scrollBarV.element,"mousedown",i),n.addListener(e.renderer.scrollBarH.element,"mousedown",i)),e.on("mousemove",function(i){if(!t.state&&!t.$dragDelay&&t.$dragEnabled){var n=e.renderer.screenToTextCoordinates(i.x,i.y),r=e.session.selection.getRange(),o=e.renderer;!r.isEmpty()&&r.insideStart(n.row,n.column)?o.setCursorStyle("default"):o.setCursorStyle("")}})};(function(){this.onMouseEvent=function(e,t){this.editor._emit(e,new a(t,this.editor))},this.onMouseMove=function(e,t){var i=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;i&&i.length&&this.editor._emit(e,new a(t,this.editor))},this.onMouseWheel=function(e,t){var i=new a(t,this.editor);i.speed=2*this.$scrollSpeed,i.wheelX=t.wheelX,i.wheelY=t.wheelY,this.editor._emit(e,i)},this.onTouchMove=function(e,t){var i=new a(t,this.editor);i.speed=1,i.wheelX=t.wheelX,i.wheelY=t.wheelY,this.editor._emit(e,i)},this.setState=function(e){this.state=e},this.captureMouse=function(e,t){this.x=e.x,this.y=e.y,this.isMousePressed=!0;var i=this.editor.renderer;i.$keepTextAreaAtCursor&&(i.$keepTextAreaAtCursor=null);var o=this,s=function(e){if(e){if(r.isWebKit&&!e.which&&o.releaseMouse)return o.releaseMouse();o.x=e.clientX,o.y=e.clientY,t&&t(e),o.mouseEvent=new a(e,o.editor),o.$mouseMoved=!0}},l=function(e){clearInterval(h),c(),o[o.state+"End"]&&o[o.state+"End"](e),o.state="",null==i.$keepTextAreaAtCursor&&(i.$keepTextAreaAtCursor=!0,i.$moveTextAreaToCursor()),o.isMousePressed=!1,o.$onCaptureMouseMove=o.releaseMouse=null,e&&o.onMouseEvent("mouseup",e)},c=function(){o[o.state]&&o[o.state](),o.$mouseMoved=!1};if(r.isOldIE&&"dblclick"==e.domEvent.type)return setTimeout(function(){l(e)});o.$onCaptureMouseMove=s,o.releaseMouse=n.capture(this.editor.container,s,l);var h=setInterval(c,20)},this.releaseMouse=null,this.cancelContextMenu=function(){var e=function(t){t&&t.domEvent&&"contextmenu"!=t.domEvent.type||(this.editor.off("nativecontextmenu",e),t&&t.domEvent&&n.stopEvent(t.domEvent))}.bind(this);setTimeout(e,10),this.editor.on("nativecontextmenu",e)}}).call(h.prototype),c.defineOptions(h.prototype,"mouseHandler",{scrollSpeed:{initialValue:2},dragDelay:{initialValue:r.isMac?150:0},dragEnabled:{initialValue:!0},focusTimout:{initialValue:0},tooltipFollowsMouse:{initialValue:!0}}),t.MouseHandler=h}),ace.define("ace/mouse/fold_handler",["require","exports","module"],function(e,t,i){"use strict";function n(e){e.on("click",function(t){var i=t.getDocumentPosition(),n=e.session,r=n.getFoldAt(i.row,i.column,1);r&&(t.getAccelKey()?n.removeFold(r):n.expandFold(r),t.stop())}),e.on("gutterclick",function(t){var i=e.renderer.$gutterLayer.getRegion(t);if("foldWidgets"==i){var n=t.getDocumentPosition().row,r=e.session;r.foldWidgets&&r.foldWidgets[n]&&e.session.onFoldWidgetClick(n,t),e.isFocused()||e.focus(),t.stop()}}),e.on("gutterdblclick",function(t){var i=e.renderer.$gutterLayer.getRegion(t);if("foldWidgets"==i){var n=t.getDocumentPosition().row,r=e.session,o=r.getParentFoldRangeData(n,!0),s=o.range||o.firstRange;if(s){n=s.start.row;var a=r.getFoldAt(n,r.getLine(n).length,1);a?r.removeFold(a):(r.addFold("...",s),e.renderer.scrollCursorIntoView({row:s.start.row,column:0}))}t.stop()}})}t.FoldHandler=n}),ace.define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"],function(e,t,i){"use strict";var n=e("../lib/keys"),r=e("../lib/event"),o=function(e){this.$editor=e,this.$data={editor:e},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0)},this.setKeyboardHandler=function(e){var t=this.$handlers;if(t[t.length-1]!=e){for(;t[t.length-1]&&t[t.length-1]!=this.$defaultHandler;)this.removeKeyboardHandler(t[t.length-1]);this.addKeyboardHandler(e,1)}},this.addKeyboardHandler=function(e,t){if(e){"function"!=typeof e||e.handleKeyboard||(e.handleKeyboard=e);var i=this.$handlers.indexOf(e);-1!=i&&this.$handlers.splice(i,1),void 0==t?this.$handlers.push(e):this.$handlers.splice(t,0,e),-1==i&&e.attach&&e.attach(this.$editor)}},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return-1==t?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.getStatusText=function(){var e=this.$data,t=e.editor;return this.$handlers.map(function(i){return i.getStatusText&&i.getStatusText(t,e)||""}).filter(Boolean).join(" ")},this.$callKeyboardHandlers=function(e,t,i,n){for(var o,s=!1,a=this.$editor.commands,l=this.$handlers.length;l--&&(o=this.$handlers[l].handleKeyboard(this.$data,e,t,i,n),!(o&&o.command&&(s="null"==o.command?!0:a.exec(o.command,this.$editor,o.args,n),s&&n&&-1!=e&&1!=o.passEvent&&1!=o.command.passEvent&&r.stopEvent(n),s))););return s||-1!=e||(o={command:"insertstring"},s=a.exec("insertstring",this.$editor,t)),s&&this.$editor._signal("keyboardActivity",o),s},this.onCommandKey=function(e,t,i){var r=n.keyCodeToString(i);this.$callKeyboardHandlers(t,r,i,e)},this.onTextInput=function(e){this.$callKeyboardHandlers(-1,e)}}).call(o.prototype),t.KeyBinding=o}),ace.define("ace/range",["require","exports","module"],function(e,t,i){"use strict";var n=function(e,t){return e.row-t.row||e.column-t.column},r=function(e,t,i,n){this.start={row:e,column:t},this.end={row:i,column:n}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return 0==this.compare(e,t)},this.compareRange=function(e){var t,i=e.end,n=e.start;return t=this.compare(i.row,i.column),1==t?(t=this.compare(n.row,n.column),1==t?2:0==t?1:0):-1==t?-2:(t=this.compare(n.row,n.column),-1==t?-1:1==t?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return 0==this.comparePoint(e.start)&&0==this.comparePoint(e.end)},this.intersects=function(e){var t=this.compareRange(e);return-1==t||0==t||1==t},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){"object"==typeof e?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){"object"==typeof e?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return 0==this.compare(e,t)?!this.isEnd(e,t)&&!this.isStart(e,t):!1},this.insideStart=function(e,t){return 0==this.compare(e,t)?!this.isEnd(e,t):!1},this.insideEnd=function(e,t){return 0==this.compare(e,t)?!this.isStart(e,t):!1},this.compare=function(e,t){return this.isMultiLine()||e!==this.start.row?ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0:tthis.end.column?1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var i={row:t+1,column:0};else if(this.end.rowt)var n={row:t+1,column:0};else if(this.start.rowt.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?s.fromPoints(t,t):this.isBackwards()?s.fromPoints(t,e):s.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.getRange().isEmpty()&&(this.$isEmpty=!0),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if("undefined"==typeof t){var i=e||this.lead;e=i.row,t=i.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var i,n="number"==typeof e?e:this.lead.row,r=this.session.getFoldLine(n);return r?(n=r.start.row,i=r.end.row):i=n,t===!0?new s(n,0,i,this.session.getLine(i).length):new s(n,0,i+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var e,t=this.lead.getPosition();if(e=this.session.getFoldAt(t.row,t.column,-1))this.moveCursorTo(e.start.row,e.start.column);else if(0===t.column)t.row>0&&this.moveCursorTo(t.row-1,this.doc.getLine(t.row-1).length);else{var i=this.session.getTabSize();this.session.isTabStop(t)&&this.doc.getLine(t.row).slice(t.column-i,t.column).split(" ").length-1==i?this.moveCursorBy(0,-i):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e,t=this.lead.getPosition();if(e=this.session.getFoldAt(t.row,t.column,1))this.moveCursorTo(e.end.row,e.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row0&&(t.column=n)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e,t=this.lead.row,i=this.lead.column,n=this.doc.getLine(t),r=n.substring(i);this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var o=this.session.getFoldAt(t,i,1);return o?void this.moveCursorTo(o.end.row,o.end.column):((e=this.session.nonTokenRe.exec(r))&&(i+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(i)),i>=n.length?(this.moveCursorTo(t,n.length),this.moveCursorRight(),void(t=i?(this.moveCursorTo(t,0),this.moveCursorLeft(),void(t>0&&this.moveCursorWordLeft())):((o=this.session.tokenRe.exec(s))&&(i-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0),void this.moveCursorTo(t,i))},this.$shortWordEndIndex=function(e){var t,i,n=0,r=/\s/,o=this.session.tokenRe;if(o.lastIndex=0,t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{for(;(i=e[n])&&r.test(i);)n++;if(1>n)for(o.lastIndex=0;(i=e[n])&&!o.test(i);)if(o.lastIndex=0,n++,r.test(i)){if(n>2){n--;break}for(;(i=e[n])&&r.test(i);)n++;if(n>2)break}}return o.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,i=this.doc.getLine(e),n=i.substring(t),r=this.session.getFoldAt(e,t,1);if(r)return this.moveCursorTo(r.end.row,r.end.column);if(t==i.length){var o=this.doc.getLength();do e++,n=this.doc.getLine(e);while(o>e&&/^\s*$/.test(n));/^\s+/.test(n)||(n=""),t=0}var s=this.$shortWordEndIndex(n);this.moveCursorTo(e,t+s)},this.moveCursorShortWordLeft=function(){var e,t=this.lead.row,i=this.lead.column;if(e=this.session.getFoldAt(t,i,-1))return this.moveCursorTo(e.start.row,e.start.column);var n=this.session.getLine(t).substring(0,i);if(0===i){do t--,n=this.doc.getLine(t);while(t>0&&/^\s*$/.test(n));i=n.length,/\s+$/.test(n)||(n="")}var o=r.stringReverse(n),s=this.$shortWordEndIndex(o);return this.moveCursorTo(t,i-s)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var i=this.session.documentToScreenPosition(this.lead.row,this.lead.column);0===t&&(this.$desiredColumn?i.column=this.$desiredColumn:this.$desiredColumn=i.column);var n=this.session.screenToDocumentPosition(i.row+e,i.column);0!==e&&0===t&&n.row===this.lead.row&&n.column===this.lead.column&&this.session.lineWidgets&&this.session.lineWidgets[n.row]&&(n.row>0||e>0)&&n.row++,this.moveCursorTo(n.row,n.column+t,0===t)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,i){var n=this.session.getFoldAt(e,t,1);n&&(e=n.start.row,t=n.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,i||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,i){var n=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(n.row,n.column,i)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e},this.getRangeOfMovements=function(e){var t=this.getCursor();try{e(this);var i=this.getCursor();return s.fromPoints(t,i)}catch(n){return s.fromPoints(t,t)}finally{this.moveCursorToPosition(t)}},this.toJSON=function(){if(this.rangeCount)var e=this.ranges.map(function(e){var t=e.clone();return t.isBackwards=e.cursor==e.start,t});else{var e=this.getRange();e.isBackwards=this.isBackwards()}return e},this.fromJSON=function(e){if(void 0==e.start){if(this.rangeList){this.toSingleRange(e[0]);for(var t=e.length;t--;){var i=s.fromPoints(e[t].start,e[t].end);e[t].isBackwards&&(i.cursor=i.start),this.addRange(i,!0)}return}e=e[0]}this.rangeList&&this.toSingleRange(e),this.setSelectionRange(e,e.isBackwards)},this.isEqual=function(e){if((e.length||this.rangeCount)&&e.length!=this.rangeCount)return!1;if(!e.length||!this.ranges)return this.getRange().isEqual(e);for(var t=this.ranges.length;t--;)if(!this.ranges[t].isEqual(e[t]))return!1;return!0}}).call(a.prototype),t.Selection=a}),ace.define("ace/tokenizer",["require","exports","module","ace/config"],function(e,t,i){"use strict";var n=e("./config"),r=2e3,o=function(e){this.states=e,this.regExps={},this.matchMappings={};for(var t in this.states){for(var i=this.states[t],n=[],r=0,o=this.matchMappings[t]={defaultToken:"text"},s="g",a=[],l=0;l1?c.onMatch=this.$applyToken:c.onMatch=c.token),d>1&&(/\\\d/.test(c.regex)?h=c.regex.replace(/\\([0-9]+)/g,function(e,t){return"\\"+(parseInt(t,10)+r+1)}):(d=1,h=this.removeCapturingGroups(c.regex)),c.splitRegex||"string"==typeof c.token||a.push(c)),o[r]=l,r+=d,n.push(h),c.onMatch||(c.onMatch=null)}}n.length||(o[0]=0,n.push("$")),a.forEach(function(e){e.splitRegex=this.createSplitterRegexp(e.regex,s)},this),this.regExps[t]=new RegExp("("+n.join(")|(")+")|($)",s)}};(function(){this.$setMaxTokenCount=function(e){r=0|e},this.$applyToken=function(e){var t=this.splitRegex.exec(e).slice(1),i=this.token.apply(this,t);if("string"==typeof i)return[{type:i,value:e}];for(var n=[],r=0,o=i.length;o>r;r++)t[r]&&(n[n.length]={type:i[r],value:t[r]});return n},this.$arrayTokens=function(e){if(!e)return[];var t=this.splitRegex.exec(e);if(!t)return"text";for(var i=[],n=this.tokenArray,r=0,o=n.length;o>r;r++)t[r+1]&&(i[i.length]={type:n[r],value:t[r+1]});return i},this.removeCapturingGroups=function(e){var t=e.replace(/\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g,function(e,t){return t?"(?:":e});return t},this.createSplitterRegexp=function(e,t){if(-1!=e.indexOf("(?=")){var i=0,n=!1,r={};e.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g,function(e,t,o,s,a,l){return n?n="]"!=a:a?n=!0:s?(i==r.stack&&(r.end=l+1,r.stack=-1),i--):o&&(i++,1!=o.length&&(r.stack=i,r.start=l)),e}),null!=r.end&&/^\)*$/.test(e.substr(r.end))&&(e=e.substring(0,r.start)+e.substr(r.end))}return"^"!=e.charAt(0)&&(e="^"+e),"$"!=e.charAt(e.length-1)&&(e+="$"),new RegExp(e,(t||"").replace("g",""))},this.getLineTokens=function(e,t){if(t&&"string"!=typeof t){var i=t.slice(0);t=i[0],"#tmp"===t&&(i.shift(),t=i.shift())}else var i=[];var n=t||"start",o=this.states[n];o||(n="start",o=this.states[n]);var s=this.matchMappings[n],a=this.regExps[n];a.lastIndex=0;for(var l,c=[],h=0,d=0,u={type:null,value:""};l=a.exec(e);){var f=s.defaultToken,p=null,m=l[0],g=a.lastIndex;if(g-m.length>h){var v=e.substring(h,g-m.length);u.type==f?u.value+=v:(u.type&&c.push(u),u={type:f,value:v})}for(var w=0;wr){for(d>2*e.length&&this.reportError("infinite loop with in ace tokenizer",{startState:t,line:e});h1&&i[0]!==n&&i.unshift("#tmp",n),{tokens:c,state:i.length?i:n}},this.reportError=n.reportError}).call(o.prototype),t.Tokenizer=o}),ace.define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"],function(e,t,i){"use strict";var n=e("../lib/lang"),r=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{defaultToken:"text"}]}};(function(){this.addRules=function(e,t){if(t)for(var i in e){for(var n=e[i],r=0;r=this.$rowTokens.length;){if(this.$row+=1,e||(e=this.$session.getLength()),this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,i=e[t].start;if(void 0!==i)return i;for(i=0;t>0;)t-=1,i+=e[t].value.length;return i},this.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}}}).call(n.prototype),t.TokenIterator=n}),ace.define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"],function(e,t,i){"use strict";var n=e("../tokenizer").Tokenizer,r=e("./text_highlight_rules").TextHighlightRules,o=e("./behaviour").Behaviour,s=e("../unicode"),a=e("../lib/lang"),l=e("../token_iterator").TokenIterator,c=e("../range").Range,h=function(){this.HighlightRules=r,this.$behaviour=new o};(function(){this.tokenRe=new RegExp("^["+s.packages.L+s.packages.Mn+s.packages.Mc+s.packages.Nd+s.packages.Pc+"\\$_]+","g"),this.nonTokenRe=new RegExp("^(?:[^"+s.packages.L+s.packages.Mn+s.packages.Mc+s.packages.Nd+s.packages.Pc+"\\$_]|\\s])+","g"),this.getTokenizer=function(){return this.$tokenizer||(this.$highlightRules=this.$highlightRules||new this.HighlightRules,this.$tokenizer=new n(this.$highlightRules.getRules())),this.$tokenizer},this.lineCommentStart="",this.blockComment="",this.toggleCommentLines=function(e,t,i,n){function r(e){for(var t=i;n>=t;t++)e(o.getLine(t),t)}var o=t.doc,s=!0,l=!0,c=1/0,h=t.getTabSize(),d=!1;if(this.lineCommentStart){if(Array.isArray(this.lineCommentStart))var u=this.lineCommentStart.map(a.escapeRegExp).join("|"),f=this.lineCommentStart[0];else var u=a.escapeRegExp(this.lineCommentStart),f=this.lineCommentStart;u=new RegExp("^(\\s*)(?:"+u+") ?"),d=t.getUseSoftTabs();var p=function(e,t){var i=e.match(u);if(i){var n=i[1].length,r=i[0].length;w(e,n,r)||" "!=i[0][r-1]||r--,o.removeInLine(t,n,r)}},m=f+" ",g=function(e,t){s&&!/\S/.test(e)||(w(e,c,c)?o.insertInLine({row:t,column:c},m):o.insertInLine({row:t,column:c},f))},v=function(e,t){return u.test(e)},w=function(e,t,i){for(var n=0;t--&&" "==e.charAt(t);)n++;if(n%h!=0)return!1;for(var n=0;" "==e.charAt(i++);)n++;return h>2?n%h!=h-1:n%h==0}}else{if(!this.blockComment)return!1;var f=this.blockComment.start,y=this.blockComment.end,u=new RegExp("^(\\s*)(?:"+a.escapeRegExp(f)+")"),A=new RegExp("(?:"+a.escapeRegExp(y)+")\\s*$"),g=function(e,t){v(e,t)||s&&!/\S/.test(e)||(o.insertInLine({row:t,column:e.length},y),o.insertInLine({row:t,column:c},f))},p=function(e,t){var i;(i=e.match(A))&&o.removeInLine(t,e.length-i[0].length,e.length),(i=e.match(u))&&o.removeInLine(t,i[1].length,i[0].length)},v=function(e,i){if(u.test(e))return!0;for(var n=t.getTokens(i),r=0;ri&&(c=i),l&&!v(e,t)&&(l=!1)):C>e.length&&(C=e.length)}),c==1/0&&(c=C,s=!1,l=!1),d&&c%h!=0&&(c=Math.floor(c/h)*h),r(l?p:g)},this.toggleBlockComment=function(e,t,i,n){var r=this.blockComment;if(r){!r.start&&r[0]&&(r=r[0]);var o,s,a=new l(t,n.row,n.column),h=a.getCurrentToken(),d=(t.selection,t.selection.toOrientedRange());if(h&&/comment/.test(h.type)){for(var u,f;h&&/comment/.test(h.type);){var p=h.value.indexOf(r.start);if(-1!=p){var m=a.getCurrentTokenRow(),g=a.getCurrentTokenColumn()+p;u=new c(m,g,m,g+r.start.length);break}h=a.stepBackward()}for(var a=new l(t,n.row,n.column),h=a.getCurrentToken();h&&/comment/.test(h.type);){var p=h.value.indexOf(r.end);if(-1!=p){var m=a.getCurrentTokenRow(),g=a.getCurrentTokenColumn()+p;f=new c(m,g,m,g+r.end.length);break}h=a.stepForward()}f&&t.remove(f),u&&(t.remove(u),o=u.start.row,s=-r.start.length)}else s=r.start.length,o=i.start.row,t.insert(i.end,r.end),t.insert(i.start,r.start);d.start.row==o&&(d.start.column+=s),d.end.row==o&&(d.end.column+=s),t.selection.fromOrientedRange(d)}},this.getNextLineIndent=function(e,t,i){return this.$getIndent(t)},this.checkOutdent=function(e,t,i){return!1},this.autoOutdent=function(e,t,i){},this.$getIndent=function(e){return e.match(/^\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){this.$embeds=[],this.$modes={};for(var t in e)e[t]&&(this.$embeds.push(t),this.$modes[t]=new e[t]);for(var i=["toggleBlockComment","toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction","getCompletions"],t=0;to;o++)if("string"==typeof r[o].token)/keyword|support|storage/.test(r[o].token)&&i.push(r[o].regex);else if("object"==typeof r[o].token)for(var a=0,l=r[o].token.length;l>a;a++)if(/keyword|support|storage/.test(r[o].token[a])){var n=r[o].regex.match(/\(.+?\)/g)[a];i.push(n.substr(1,n.length-2))}this.completionKeywords=i}return e?i.concat(this.$keywordList||[]):this.$keywordList},this.$createKeywordList=function(){return this.$highlightRules||this.getTokenizer(),this.$keywordList=this.$highlightRules.$keywordList||[]},this.getCompletions=function(e,t,i,n){var r=this.$keywordList||this.$createKeywordList();return r.map(function(e){return{name:e,value:e,score:0,meta:"keyword"}})},this.$id="ace/mode/text"}).call(h.prototype),t.Mode=h}),ace.define("ace/apply_delta",["require","exports","module"],function(e,t,i){"use strict";t.applyDelta=function(e,t,i){var n=t.start.row,r=t.start.column,o=e[n]||"";switch(t.action){case"insert":var s=t.lines;if(1===s.length)e[n]=o.substring(0,r)+t.lines[0]+o.substring(r);else{var a=[n,1].concat(t.lines);e.splice.apply(e,a),e[n]=o.substring(0,r)+e[n],e[n+t.lines.length-1]+=o.substring(r)}break;case"remove":var l=t.end.column,c=t.end.row;n===c?e[n]=o.substring(0,r)+o.substring(l):e.splice(n,c-n+1,o.substring(0,r)+e[c].substring(l))}}}),ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/event_emitter").EventEmitter,o=t.Anchor=function(e,t,i){this.$onChange=this.onChange.bind(this),this.attach(e),"undefined"==typeof i?this.setPosition(t.row,t.column):this.setPosition(t,i)};(function(){function e(e,t,i){var n=i?e.column<=t.column:e.columnthis.row)){var i=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(i.row,i.column,!0)}},this.setPosition=function(e,t,i){var n;if(n=i?{row:e,column:t}:this.$clipPositionToDocument(e,t),this.row!=n.row||this.column!=n.column){var r={row:this.row,column:this.column};this.row=n.row,this.column=n.column,this._signal("change",{old:r,value:n})}},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var i={};return e>=this.document.getLength()?(i.row=Math.max(0,this.document.getLength()-1),i.column=this.document.getLine(i.row).length):0>e?(i.row=0,i.column=0):(i.row=e,i.column=Math.min(this.document.getLine(i.row).length,Math.max(0,t))),0>t&&(i.column=0),i}}).call(o.prototype)}),ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./apply_delta").applyDelta,o=e("./lib/event_emitter").EventEmitter,s=e("./range").Range,a=e("./anchor").Anchor,l=function(e){this.$lines=[""],0===e.length?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){n.implement(this,o),this.setValue=function(e){var t=this.getLength()-1;this.remove(new s(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new a(this,e,t)},0==="aaa".split(/a/).length?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){this.$newLineMode!==e&&(this.$newLineMode=e,this._signal("changeNewLineMode"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return"\r\n"==e||"\r"==e||"\n"==e},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var i=t.length-1;e.end.row-e.start.row==i&&(t[i]=t[i].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var i=this.clippedPos(e.row,e.column),n=this.pos(e.row,e.column+t.length);return this.applyDelta({start:i,end:n,action:"insert",lines:[t]},!0),this.clonePos(n)},this.clippedPos=function(e,t){var i=this.getLength();void 0===e?e=i:0>e?e=0:e>=i&&(e=i-1,t=void 0);var n=this.getLine(e);return void 0==t&&(t=n.length),t=Math.min(Math.max(t,0),n.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var i=0;e0,n=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){if(e instanceof s||(e=s.fromPoints(e.start,e.end)),0===t.length&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var i;return i=t?this.insert(e.start,t):e.start},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var i="insert"==e.action;(i?e.lines.length<=1&&!e.lines[0]:!s.comparePoints(e.start,e.end))||(i&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),r(this.$lines,e,t),this._signal("change",e))},this.$splitAndapplyLargeDelta=function(e,t){for(var i=e.lines,n=i.length,r=e.start.row,o=e.start.column,s=0,a=0;;){s=a,a+=t-1;var l=i.slice(s,a);if(a>n){e.lines=l,e.start.row=r+s,e.start.column=o;break}l.push(""),this.applyDelta({start:this.pos(r+s,o),end:this.pos(r+a,o=0),action:e.action,lines:l},!0)}},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:"insert"==e.action?"remove":"insert",lines:e.lines.slice()})},this.indexToPosition=function(e,t){for(var i=this.$lines||this.getAllLines(),n=this.getNewLineCharacter().length,r=t||0,o=i.length;o>r;r++)if(e-=i[r].length+n,0>e)return{row:r,column:e+i[r].length+n};return{row:o-1,column:i[o-1].length}},this.positionToIndex=function(e,t){for(var i=this.$lines||this.getAllLines(),n=this.getNewLineCharacter().length,r=0,o=Math.min(e.row,i.length),s=t||0;o>s;++s)r+=i[s].length+n;return r+e.column}}).call(l.prototype),t.Document=l}),ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/event_emitter").EventEmitter,o=function(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var i=this;this.$worker=function(){if(i.running){for(var e=new Date,t=i.currentLine,n=-1,r=i.doc,o=t;i.lines[t];)t++;var s=r.getLength(),a=0;for(i.running=!1;s>t;){i.$tokenizeRow(t),n=t;do t++;while(i.lines[t]);if(a++,a%5===0&&new Date-e>20){i.running=setTimeout(i.$worker,20);break}}i.currentLine=t,n>=o&&i.fireUpdateEvent(o,n)}}};(function(){n.implement(this,r),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var i={first:e,last:t};this._signal("update",{data:i})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},this.$updateOnChange=function(e){var t=e.start.row,i=e.end.row-t;if(0===i)this.lines[t]=null;else if("remove"==e.action)this.lines.splice(t,i+1,null),this.states.splice(t,i+1,null);else{var n=Array(i+1);n.unshift(t,1),this.lines.splice.apply(this.lines,n),this.states.splice.apply(this.states,n)}this.currentLine=Math.min(t,this.currentLine,this.doc.getLength()),this.stop()},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||"start"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),i=this.states[e-1],n=this.tokenizer.getLineTokens(t,i,e);return this.states[e]+""!=n.state+""?(this.states[e]=n.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=n.tokens}}).call(o.prototype),t.BackgroundTokenizer=o}),ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,i){"use strict";var n=e("./lib/lang"),r=(e("./lib/oop"),e("./range").Range),o=function(e,t,i){this.setRegexp(e),this.clazz=t,this.type=i||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){this.regExp+""!=e+""&&(this.regExp=e,this.cache=[])},this.update=function(e,t,i,o){if(this.regExp)for(var s=o.firstRow,a=o.lastRow,l=s;a>=l;l++){var c=this.cache[l];null==c&&(c=n.getMatchOffsets(i.getLine(l),this.regExp),c.length>this.MAX_RANGES&&(c=c.slice(0,this.MAX_RANGES)),c=c.map(function(e){return new r(l,e.offset,l,e.offset+e.length)}),this.cache[l]=c.length?c:"");for(var h=c.length;h--;)t.drawSingleLineMarker(e,c[h].toScreenRange(i),this.clazz,o)}}}).call(o.prototype),t.SearchHighlight=o}),ace.define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(e,t,i){"use strict";function n(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var i=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,i.end.row,i.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e("../range").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.rowthis.endRow)throw new Error("Can't add a fold to this FoldLine as it has no connection");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,i){var n,r,o,s=0,a=this.folds,l=!0;null==t&&(t=this.end.row,i=this.end.column);for(var c=0;ce)return{row:n.start.row,column:n.start.column+e};if(e-=n.placeholder.length,0>e)return n.start;t=n.end.column}return{row:this.end.row,column:this.end.column+e}}}).call(n.prototype),t.FoldLine=n}),ace.define("ace/range_list",["require","exports","module","ace/range"],function(e,t,i){"use strict";var n=e("./range").Range,r=n.comparePoints,o=function(){this.ranges=[]};(function(){this.comparePoints=r,this.pointIndex=function(e,t,i){for(var n=this.ranges,o=i||0;o0)){var l=r(e,s.start);return 0===a?t&&0!==l?-o-2:o:l>0||0===l&&!t?o:-o-1}}return-o-1},this.add=function(e){var t=!e.isEmpty(),i=this.pointIndex(e.start,t);0>i&&(i=-i-1);var n=this.pointIndex(e.end,t,i);return 0>n?n=-n-1:n++,this.ranges.splice(i,n-i,e)},this.addList=function(e){for(var t=[],i=e.length;i--;)t.push.apply(t,this.add(e[i]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);return t>=0?this.ranges.splice(t,1):void 0},this.merge=function(){var e=[],t=this.ranges;t=t.sort(function(e,t){return r(e.start,t.start)});for(var i,n=t[0],o=1;os||(0!=s||i.isEmpty()||n.isEmpty())&&(r(i.end,n.end)<0&&(i.end.row=n.end.row,i.end.column=n.end.column),t.splice(o,1),e.push(n),n=i,o--)}return this.ranges=t,e},this.contains=function(e,t){return this.pointIndex({row:e,column:t})>=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);return t>=0?this.ranges[t]:void 0},this.clipRows=function(e,t){var i=this.ranges;if(i[0].start.row>t||i[i.length-1].start.rown&&(n=-n-1);var r=this.pointIndex({row:t,column:0},n);0>r&&(r=-r-1);for(var o=[],s=n;r>s;s++)o.push(i[s]);return o},this.removeAll=function(){return this.ranges.splice(0,this.ranges.length)},this.attach=function(e){this.session&&this.detach(),this.session=e,this.onChange=this.$onChange.bind(this),this.session.on("change",this.onChange)},this.detach=function(){this.session&&(this.session.removeListener("change",this.onChange),this.session=null)},this.$onChange=function(e){if("insert"==e.action)var t=e.start,i=e.end;else var i=e.start,t=e.end;for(var n=t.row,r=i.row,o=r-n,s=-t.column+i.column,a=this.ranges,l=0,c=a.length;c>l;l++){var h=a[l];if(!(h.end.rown)break;if(h.start.row==n&&h.start.column>=t.column&&(h.start.column==t.column&&this.$insertRight||(h.start.column+=s,h.start.row+=o)),h.end.row==n&&h.end.column>=t.column){if(h.end.column==t.column&&this.$insertRight)continue;h.end.column==t.column&&s>0&&c-1>l&&h.end.column>h.start.column&&h.end.column==a[l+1].start.column&&(h.end.column-=s),h.end.column+=s,h.end.row+=o}}}if(0!=o&&c>l)for(;c>l;l++){var h=a[l];h.start.row+=o,h.end.row+=o}}}).call(o.prototype),t.RangeList=o}),ace.define("ace/edit_session/fold",["require","exports","module","ace/range","ace/range_list","ace/lib/oop"],function(e,t,i){"use strict";function n(e,t){e.row-=t.row,0==e.row&&(e.column-=t.column)}function r(e,t){n(e.start,t),n(e.end,t)}function o(e,t){0==e.row&&(e.column+=t.column),e.row+=t.row}function s(e,t){o(e.start,t),o(e.end,t)}var a=(e("../range").Range,e("../range_list").RangeList),l=e("../lib/oop"),c=t.Fold=function(e,t){this.foldLine=null,this.placeholder=t,this.range=e,this.start=e.start,this.end=e.end,this.sameRow=e.start.row==e.end.row,this.subFolds=this.ranges=[]};l.inherits(c,a),function(){this.toString=function(){return'"'+this.placeholder+'" '+this.range.toString()},this.setFoldLine=function(e){this.foldLine=e,this.subFolds.forEach(function(t){t.setFoldLine(e)})},this.clone=function(){var e=this.range.clone(),t=new c(e,this.placeholder);return this.subFolds.forEach(function(e){t.subFolds.push(e.clone())}),t.collapseChildren=this.collapseChildren,t},this.addSubFold=function(e){if(!this.range.isEqual(e)){if(!this.range.containsRange(e))throw new Error("A fold can't intersect already existing fold"+e.range+this.range);r(e,this.start);for(var t=e.start.row,i=e.start.column,n=0,o=-1;n=e)return r;if(r.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var i=this.$foldData,n=0;for(t&&(n=i.indexOf(t)),-1==n&&(n=0),n;n=e)return r}return null},this.getFoldedRowCount=function(e,t){for(var i=this.$foldData,n=t-e+1,r=0;r=t){t>a&&(a>=e?n-=t-a:n=0);break}s>=e&&(n-=a>=e?s-a:s-e+1)}return n},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var i,n=this.$foldData,r=!1;e instanceof s?i=e:(i=new s(t,e),i.collapseChildren=t.collapseChildren),this.$clipRangeToDocument(i.range);var a=i.start.row,l=i.start.column,c=i.end.row,h=i.end.column;if(!(c>a||a==c&&h-2>=l))throw new Error("The range has to be at least 2 characters width");var d=this.getFoldAt(a,l,1),u=this.getFoldAt(c,h,-1);if(d&&u==d)return d.addSubFold(i);d&&!d.range.isStart(a,l)&&this.removeFold(d),u&&!u.range.isEnd(c,h)&&this.removeFold(u);var f=this.getFoldsInRange(i.range);f.length>0&&(this.removeFolds(f),f.forEach(function(e){i.addSubFold(e)}));for(var p=0;p0&&this.foldAll(e.start.row+1,e.end.row,e.collapseChildren-1),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var i,n;if(null==e?(i=new r(0,0,this.getLength(),0),t=!0):i="number"==typeof e?new r(e,0,e,this.getLine(e).length):"row"in e?r.fromPoints(e,e):e,n=this.getFoldsInRangeList(i),t)this.removeFolds(n);else for(var o=n;o.length;)this.expandFolds(o),o=this.getFoldsInRangeList(i);return n.length?n:void 0},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var i=this.getFoldLine(e,t);return i?i.end.row:e},this.getRowFoldStart=function(e,t){var i=this.getFoldLine(e,t);return i?i.start.row:e},this.getFoldDisplayLine=function(e,t,i,n,r){null==n&&(n=e.start.row),null==r&&(r=0),null==t&&(t=e.end.row),null==i&&(i=this.getLine(t).length);var o=this.doc,s="";return e.walk(function(e,t,i,a){if(!(n>t)){if(t==n){if(r>i)return;a=Math.max(r,a)}s+=null!=e?e:o.getLine(t).substring(a,i)}},t,i),s},this.getDisplayLine=function(e,t,i,n){var r=this.getFoldLine(e);if(r)return this.getFoldDisplayLine(r,e,t,i,n);var o;return o=this.doc.getLine(e),o.substring(n||0,t||o.length)},this.$cloneFoldData=function(){var e=[];return e=this.$foldData.map(function(t){var i=t.folds.map(function(e){return e.clone()});return new o(e,i)})},this.toggleFold=function(e){var t,i,n=this.selection,r=n.getRange();if(r.isEmpty()){var o=r.start;if(t=this.getFoldAt(o.row,o.column))return void this.expandFold(t);(i=this.findMatchingBracket(o))?1==r.comparePoint(i)?r.end=i:(r.start=i,r.start.column++,r.end.column--):(i=this.findMatchingBracket({row:o.row,column:o.column+1}))?(1==r.comparePoint(i)?r.end=i:r.start=i,r.start.column++):r=this.getCommentFoldRange(o.row,o.column)||r}else{var s=this.getFoldsInRange(r);if(e&&s.length)return void this.expandFolds(s);1==s.length&&(t=s[0])}if(t||(t=this.getFoldAt(r.start.row,r.start.column)),t&&t.range.toString()==r.toString())return void this.expandFold(t);var a="...";if(!r.isMultiLine()){if(a=this.getTextRange(r),a.length<4)return;a=a.trim().substring(0,2)+".."}this.addFold(a,r)},this.getCommentFoldRange=function(e,t,i){var n=new a(this,e,t),o=n.getCurrentToken();if(o&&/^comment|string/.test(o.type)){var s=new r,l=new RegExp(o.type.replace(/\..*/,"\\."));if(1!=i){do o=n.stepBackward();while(o&&l.test(o.type));n.stepForward()}if(s.start.row=n.getCurrentTokenRow(),s.start.column=n.getCurrentTokenColumn()+2,n=new a(this,e,t),-1!=i){do o=n.stepForward();while(o&&l.test(o.type));o=n.stepBackward()}else o=n.getCurrentToken();return s.end.row=n.getCurrentTokenRow(),s.end.column=n.getCurrentTokenColumn()+o.value.length-2,s}},this.foldAll=function(e,t,i){void 0==i&&(i=1e5);var n=this.foldWidgets;if(n){t=t||this.getLength(),e=e||0;for(var r=e;t>r;r++)if(null==n[r]&&(n[r]=this.getFoldWidget(r)),"start"==n[r]){var o=this.getFoldWidgetRange(r);if(o&&o.isMultiLine()&&o.end.row<=t&&o.start.row>=e){r=o.end.row;try{var s=this.addFold("...",o);s&&(s.collapseChildren=i)}catch(a){}}}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error("invalid fold style: "+e+"["+Object.keys(this.$foldStyles).join(", ")+"]");if(this.$foldStyle!=e){this.$foldStyle=e,"manual"==e&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)}},this.$setFolding=function(e){if(this.$foldMode!=e){if(this.$foldMode=e,this.off("change",this.$updateFoldWidgets),this.off("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets),this._signal("changeAnnotation"),!e||"manual"==this.$foldStyle)return void(this.foldWidgets=null);this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.$tokenizerUpdateFoldWidgets=this.tokenizerUpdateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets),this.on("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets)}},this.getParentFoldRangeData=function(e,t){var i=this.foldWidgets;if(!i||t&&i[e])return{};for(var n,r=e-1;r>=0;){var o=i[r];if(null==o&&(o=i[r]=this.getFoldWidget(r)),"start"==o){var s=this.getFoldWidgetRange(r);if(n||(n=s),s&&s.end.row>=e)break}r--}return{range:-1!==r&&s,firstRange:n}},this.onFoldWidgetClick=function(e,t){t=t.domEvent;var i={children:t.shiftKey,all:t.ctrlKey||t.metaKey,siblings:t.altKey},n=this.$toggleFoldWidget(e,i);if(!n){var r=t.target||t.srcElement;r&&/ace_fold-widget/.test(r.className)&&(r.className+=" ace_invalid")}},this.$toggleFoldWidget=function(e,t){if(this.getFoldWidget){var i=this.getFoldWidget(e),n=this.getLine(e),r="end"===i?-1:1,o=this.getFoldAt(e,-1===r?0:n.length,r);if(o)return void(t.children||t.all?this.removeFold(o):this.expandFold(o));var s=this.getFoldWidgetRange(e,!0);if(s&&!s.isMultiLine()&&(o=this.getFoldAt(s.start.row,s.start.column,1),o&&s.isEqual(o.range)))return void this.removeFold(o);if(t.siblings){var a=this.getParentFoldRangeData(e);if(a.range)var l=a.range.start.row+1,c=a.range.end.row;this.foldAll(l,c,t.all?1e4:0)}else t.children?(c=s?s.end.row:this.getLength(),this.foldAll(e+1,c,t.all?1e4:0)):s&&(t.all&&(s.collapseChildren=1e4),this.addFold("...",s));return s}},this.toggleFoldWidget=function(e){var t=this.selection.getCursor().row;t=this.getRowFoldStart(t);var i=this.$toggleFoldWidget(t,{});if(!i){var n=this.getParentFoldRangeData(t,!0);if(i=n.range||n.firstRange){t=i.start.row;var r=this.getFoldAt(t,this.getLine(t).length,1);r?this.removeFold(r):this.addFold("...",i)}}},this.updateFoldWidgets=function(e){var t=e.start.row,i=e.end.row-t;if(0===i)this.foldWidgets[t]=null;else if("remove"==e.action)this.foldWidgets.splice(t,i+1,null);else{var n=Array(i+1);n.unshift(t,1),this.foldWidgets.splice.apply(this.foldWidgets,n)}},this.tokenizerUpdateFoldWidgets=function(e){var t=e.data;t.first!=t.last&&this.foldWidgets.length>t.first&&this.foldWidgets.splice(t.first,this.foldWidgets.length)}}var r=e("../range").Range,o=e("./fold_line").FoldLine,s=e("./fold").Fold,a=e("../token_iterator").TokenIterator;t.Folding=n}),ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,t,i){"use strict";function n(){this.findMatchingBracket=function(e,t){if(0==e.column)return null;var i=t||this.getLine(e.row).charAt(e.column-1);if(""==i)return null;var n=i.match(/([\(\[\{])|([\)\]\}])/);return n?n[1]?this.$findClosingBracket(n[1],e):this.$findOpeningBracket(n[2],e):null},this.getBracketRange=function(e){var t,i=this.getLine(e.row),n=!0,r=i.charAt(e.column-1),s=r&&r.match(/([\(\[\{])|([\)\]\}])/);if(s||(r=i.charAt(e.column),e={row:e.row,column:e.column+1},s=r&&r.match(/([\(\[\{])|([\)\]\}])/),n=!1),!s)return null;if(s[1]){var a=this.$findClosingBracket(s[1],e);if(!a)return null;t=o.fromPoints(e,a),n||(t.end.column++,t.start.column--),t.cursor=t.end}else{var a=this.$findOpeningBracket(s[2],e);if(!a)return null;t=o.fromPoints(a,e),n||(t.start.column++,t.end.column--),t.cursor=t.start}return t},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(e,t,i){ +var n=this.$brackets[e],o=1,s=new r(this,t.row,t.column),a=s.getCurrentToken();if(a||(a=s.stepForward()),a){i||(i=new RegExp("(\\.?"+a.type.replace(".","\\.").replace("rparen",".paren").replace(/\b(?:end)\b/,"(?:start|begin|end)")+")+"));for(var l=t.column-s.getCurrentTokenColumn()-2,c=a.value;;){for(;l>=0;){var h=c.charAt(l);if(h==n){if(o-=1,0==o)return{row:s.getCurrentTokenRow(),column:l+s.getCurrentTokenColumn()}}else h==e&&(o+=1);l-=1}do a=s.stepBackward();while(a&&!i.test(a.type));if(null==a)break;c=a.value,l=c.length-1}return null}},this.$findClosingBracket=function(e,t,i){var n=this.$brackets[e],o=1,s=new r(this,t.row,t.column),a=s.getCurrentToken();if(a||(a=s.stepForward()),a){i||(i=new RegExp("(\\.?"+a.type.replace(".","\\.").replace("lparen",".paren").replace(/\b(?:start|begin)\b/,"(?:start|begin|end)")+")+"));for(var l=t.column-s.getCurrentTokenColumn();;){for(var c=a.value,h=c.length;h>l;){var d=c.charAt(l);if(d==n){if(o-=1,0==o)return{row:s.getCurrentTokenRow(),column:l+s.getCurrentTokenColumn()}}else d==e&&(o+=1);l+=1}do a=s.stepForward();while(a&&!i.test(a.type));if(null==a)break;l=0}return null}}}var r=e("../token_iterator").TokenIterator,o=e("../range").Range;t.BracketMatch=n}),ace.define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/config","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/lang"),o=e("./config"),s=e("./lib/event_emitter").EventEmitter,a=e("./selection").Selection,l=e("./mode/text").Mode,c=e("./range").Range,h=e("./document").Document,d=e("./background_tokenizer").BackgroundTokenizer,u=e("./search_highlight").SearchHighlight,f=function(e,t){this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$undoSelect=!0,this.$foldData=[],this.$foldData.toString=function(){return this.join("\n")},this.on("changeFold",this.onChangeFold.bind(this)),this.$onChange=this.onChange.bind(this),"object"==typeof e&&e.getLine||(e=new h(e)),this.setDocument(e),this.selection=new a(this),o.resetOptions(this),this.setMode(t),o._signal("session",this)};(function(){function e(e){return 4352>e?!1:e>=4352&&4447>=e||e>=4515&&4519>=e||e>=4602&&4607>=e||e>=9001&&9002>=e||e>=11904&&11929>=e||e>=11931&&12019>=e||e>=12032&&12245>=e||e>=12272&&12283>=e||e>=12288&&12350>=e||e>=12353&&12438>=e||e>=12441&&12543>=e||e>=12549&&12589>=e||e>=12593&&12686>=e||e>=12688&&12730>=e||e>=12736&&12771>=e||e>=12784&&12830>=e||e>=12832&&12871>=e||e>=12880&&13054>=e||e>=13056&&19903>=e||e>=19968&&42124>=e||e>=42128&&42182>=e||e>=43360&&43388>=e||e>=44032&&55203>=e||e>=55216&&55238>=e||e>=55243&&55291>=e||e>=63744&&64255>=e||e>=65040&&65049>=e||e>=65072&&65106>=e||e>=65108&&65126>=e||e>=65128&&65131>=e||e>=65281&&65376>=e||e>=65504&&65510>=e}n.implement(this,s),this.setDocument=function(e){this.doc&&this.doc.removeListener("change",this.$onChange),this.doc=e,e.on("change",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e)return this.$docRowCache=[],void(this.$screenRowCache=[]);var t=this.$docRowCache.length,i=this.$getRowCacheIndex(this.$docRowCache,e)+1;t>i&&(this.$docRowCache.splice(i,t),this.$screenRowCache.splice(i,t))},this.$getRowCacheIndex=function(e,t){for(var i=0,n=e.length-1;n>=i;){var r=i+n>>1,o=e[r];if(t>o)i=r+1;else{if(!(o>t))return r;n=r-1}}return i-1},this.resetCaches=function(){this.$modified=!0,this.$wrapData=[],this.$rowLengthCache=[],this.$resetRowCache(0),this.bgTokenizer&&this.bgTokenizer.start(0)},this.onChangeFold=function(e){var t=e.data;this.$resetRowCache(t.start.row)},this.onChange=function(e){this.$modified=!0,this.$resetRowCache(e.start.row);var t=this.$updateInternalDataOnChange(e);this.$fromUndo||!this.$undoManager||e.ignore||(this.$deltasDoc.push(e),t&&0!=t.length&&this.$deltasFold.push({action:"removeFolds",folds:t}),this.$informUndoManager.schedule()),this.bgTokenizer&&this.bgTokenizer.$updateOnChange(e),this._signal("change",e)},this.setValue=function(e){this.doc.setValue(e),this.selection.moveTo(0,0),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.setUndoManager(this.$undoManager),this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(e){return this.bgTokenizer.getState(e)},this.getTokens=function(e){return this.bgTokenizer.getTokens(e)},this.getTokenAt=function(e,t){var i,n=this.bgTokenizer.getTokens(e),r=0;if(null==t)o=n.length-1,r=this.getLine(e).length;else for(var o=0;o=t));o++);return(i=n[o])?(i.index=o,i.start=r-i.value.length,i):null},this.setUndoManager=function(e){if(this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel(),e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:"fold",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:"doc",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:"aceupdate",args:[t.$deltas,t],merge:t.mergeUndoDeltas}),t.mergeUndoDeltas=!1,t.$deltas=[]},this.$informUndoManager=r.delayedCall(this.$syncInformUndoManager)}},this.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?r.stringRepeat(" ",this.getTabSize()):" "},this.setUseSoftTabs=function(e){this.setOption("useSoftTabs",e)},this.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},this.setTabSize=function(e){this.setOption("tabSize",e)},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize===0},this.$overwrite=!1,this.setOverwrite=function(e){this.setOption("overwrite",e)},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=""),this.$decorations[e]+=" "+t,this._signal("changeBreakpoint",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||"").replace(" "+t,""),this._signal("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t0&&(n=!!i.charAt(t-1).match(this.tokenRe)),n||(n=!!i.charAt(t).match(this.tokenRe)),n)var r=this.tokenRe;else if(/^\s+$/.test(i.slice(t-1,t+1)))var r=/\s/;else var r=this.nonTokenRe;var o=t;if(o>0){do o--;while(o>=0&&i.charAt(o).match(r));o++}for(var s=t;se&&(e=t.screenWidth)}),this.lineWidgetWidth=e},this.$computeWidth=function(e){if(this.$modified||e){if(this.$modified=!1,this.$useWrapMode)return this.screenWidth=this.$wrapLimit;for(var t=this.doc.getAllLines(),i=this.$rowLengthCache,n=0,r=0,o=this.$foldData[r],s=o?o.start.row:1/0,a=t.length,l=0;a>l;l++){if(l>s){if(l=o.end.row+1,l>=a)break;o=this.$foldData[r++],s=o?o.start.row:1/0}null==i[l]&&(i[l]=this.$getStringScreenWidth(t[l])[0]),i[l]>n&&(n=i[l])}this.screenWidth=n}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.removeFullLines=function(e,t){return this.doc.removeFullLines(e,t)},this.undoChanges=function(e,t){if(e.length){this.$fromUndo=!0;for(var i=null,n=e.length-1;-1!=n;n--){var r=e[n];"doc"==r.group?(this.doc.revertDeltas(r.deltas),i=this.$getUndoSelection(r.deltas,!0,i)):r.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,i&&this.$undoSelect&&!t&&this.selection.setSelectionRange(i),i}},this.redoChanges=function(e,t){if(e.length){this.$fromUndo=!0;for(var i=null,n=0;ne.end.column&&(o.start.column+=a),o.end.row==e.end.row&&o.end.column>e.end.column&&(o.end.column+=a)),s&&o.start.row>=e.end.row&&(o.start.row+=s,o.end.row+=s)}if(o.end=this.insert(o.start,n),r.length){var l=e.start,h=o.start,s=h.row-l.row,a=h.column-l.column;this.addFolds(r.map(function(e){return e=e.clone(),e.start.row==l.row&&(e.start.column+=a),e.end.row==l.row&&(e.end.column+=a),e.start.row+=s,e.end.row+=s,e}))}return o},this.indentRows=function(e,t,i){i=i.replace(/\t/g,this.getTabString());for(var n=e;t>=n;n++)this.doc.insertInLine({row:n,column:0},i)},this.outdentRows=function(e){for(var t=e.collapseRows(),i=new c(0,0,0,0),n=this.getTabSize(),r=t.start.row;r<=t.end.row;++r){var o=this.getLine(r);i.start.row=r,i.end.row=r;for(var s=0;n>s&&" "==o.charAt(s);++s);n>s&&" "==o.charAt(s)?(i.start.column=s,i.end.column=s+1):(i.start.column=0,i.end.column=s),this.remove(i)}},this.$moveLines=function(e,t,i){if(e=this.getRowFoldStart(e),t=this.getRowFoldEnd(t),0>i){var n=this.getRowFoldStart(e+i);if(0>n)return 0;var r=n-e}else if(i>0){var n=this.getRowFoldEnd(t+i);if(n>this.doc.getLength()-1)return 0;var r=n-t}else{e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t);var r=t-e+1}var o=new c(e,0,t,Number.MAX_VALUE),s=this.getFoldsInRange(o).map(function(e){return e=e.clone(),e.start.row+=r,e.end.row+=r,e}),a=0==i?this.doc.getLines(e,t):this.doc.removeFullLines(e,t);return this.doc.insertFullLines(e+r,a),s.length&&this.addFolds(s),r},this.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},this.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},this.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return 0>t?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){if(t=Math.max(0,t),0>e)e=0,t=0;else{var i=this.doc.getLength();e>=i?(e=i-1,t=this.doc.getLine(i-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){if(this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0),e){var t=this.getLength();this.$wrapData=Array(t),this.$updateWrapData(0,t-1)}this._signal("changeWrapMode")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){this.$wrapLimitRange.min===e&&this.$wrapLimitRange.max===t||(this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this.$useWrapMode&&this._signal("changeWrapMode"))},this.adjustWrapLimit=function(e,t){var i=this.$wrapLimitRange;i.max<0&&(i={min:t,max:t});var n=this.$constrainWrapLimit(e,i.min,i.max);return n!=this.$wrapLimit&&n>1?(this.$wrapLimit=n,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(e,t,i){return t&&(e=Math.max(t,e)),i&&(e=Math.min(i,e)),e},this.getWrapLimit=function(){return this.$wrapLimit},this.setWrapLimit=function(e){this.setWrapLimitRange(e,e)},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,i=e.action,n=e.start,r=e.end,o=n.row,s=r.row,a=s-o,l=null;if(this.$updating=!0,0!=a)if("remove"===i){this[t?"$wrapData":"$rowLengthCache"].splice(o,a);var c=this.$foldData;l=this.getFoldsInRange(e),this.removeFolds(l);var h=this.getFoldLine(r.row),d=0;if(h){h.addRemoveChars(r.row,r.column,n.column-r.column),h.shiftRow(-a);var u=this.getFoldLine(o);u&&u!==h&&(u.merge(h),h=u),d=c.indexOf(h)+1}for(d;d=r.row&&h.shiftRow(-a)}s=o}else{var f=Array(a);f.unshift(o,0);var p=t?this.$wrapData:this.$rowLengthCache;p.splice.apply(p,f);var c=this.$foldData,h=this.getFoldLine(o),d=0;if(h){var m=h.range.compareInside(n.row,n.column);0==m?(h=h.split(n.row,n.column),h&&(h.shiftRow(a),h.addRemoveChars(s,0,r.column-n.column))):-1==m&&(h.addRemoveChars(o,0,r.column-n.column),h.shiftRow(a)),d=c.indexOf(h)+1}for(d;d=o&&h.shiftRow(a)}}else{a=Math.abs(e.start.column-e.end.column),"remove"===i&&(l=this.getFoldsInRange(e),this.removeFolds(l),a=-a);var h=this.getFoldLine(o);h&&h.addRemoveChars(o,n.column,a)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),this.$updating=!1,t?this.$updateWrapData(o,s):this.$updateRowLengthCache(o,s),l},this.$updateRowLengthCache=function(e,t,i){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var i,n,r=this.doc.getAllLines(),o=this.getTabSize(),s=this.$wrapData,l=this.$wrapLimit,c=e;for(t=Math.min(t,r.length-1);t>=c;)n=this.getFoldLine(c,n),n?(i=[],n.walk(function(e,t,n,o){var s;if(null!=e){s=this.$getDisplayTokens(e,i.length),s[0]=a;for(var l=1;lt-y;){var A=c+t-y;if(e[A-1]>=p&&e[A]>=p)o(A);else if(e[A]!=a&&e[A]!=h){for(var C=Math.max(A-(t-(t>>2)),c-1);A>C&&e[A]C&&e[A]C&&e[A]==f;)A--}else for(;A>C&&e[A]C?o(++A):(A=c+t,e[A]==i&&A--,o(A-y))}else{for(A;A!=c-1&&e[A]!=a;A--);if(A>c){o(A);continue}for(A=c+t;Ac;c++)s.push(g)}else 32==l?s.push(p):l>39&&48>l||l>57&&64>l?s.push(f):l>=4352&&e(l)?s.push(t,i):s.push(t)}return s},this.$getStringScreenWidth=function(t,i,n){if(0==i)return[0,0];null==i&&(i=1/0),n=n||0;var r,o;for(o=0;o=4352&&e(r)?2:1,!(n>i));o++);return[n,o]},this.lineWidgets=null,this.getRowLength=function(e){if(this.lineWidgets)var t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0;else t=0;return this.$useWrapMode&&this.$wrapData[e]?this.$wrapData[e].length+1+t:1+t},this.getRowLineCount=function(e){return this.$useWrapMode&&this.$wrapData[e]?this.$wrapData[e].length+1:1},this.getRowWrapIndent=function(e){if(this.$useWrapMode){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE),i=this.$wrapData[t.row];return i.length&&i[0]e)return{row:0,column:0};var i,n,r=0,o=0,s=0,a=0,l=this.$screenRowCache,c=this.$getRowCacheIndex(l,e),h=l.length;if(h&&c>=0)var s=l[c],r=this.$docRowCache[c],d=e>l[h-1];else var d=!h;for(var u=this.getLength()-1,f=this.getNextFoldLine(r),p=f?f.start.row:1/0;e>=s&&(a=this.getRowLength(r),!(s+a>e||r>=u));)s+=a,r++,r>p&&(r=f.end.row+1,f=this.getNextFoldLine(r,f),p=f?f.start.row:1/0),d&&(this.$docRowCache.push(r),this.$screenRowCache.push(s));if(f&&f.start.row<=r)i=this.getFoldDisplayLine(f),r=f.start.row;else{if(e>=s+a||r>u)return{row:u,column:this.getLine(u).length};i=this.getLine(r),f=null}var m=0;if(this.$useWrapMode){var g=this.$wrapData[r];if(g){var v=Math.floor(e-s);n=g[v],v>0&&g.length&&(m=g.indent,o=g[v-1]||g[g.length-1],i=i.substring(o))}}return o+=this.$getStringScreenWidth(i,t-m)[1],this.$useWrapMode&&o>=n&&(o=n-1),f?f.idxToPosition(o):{row:r,column:o}},this.documentToScreenPosition=function(e,t){if("undefined"==typeof t)var i=this.$clipPositionToDocument(e.row,e.column);else i=this.$clipPositionToDocument(e,t);e=i.row,t=i.column;var n=0,r=null,o=null;o=this.getFoldAt(e,t,1),o&&(e=o.start.row,t=o.start.column);var s,a=0,l=this.$docRowCache,c=this.$getRowCacheIndex(l,e),h=l.length;if(h&&c>=0)var a=l[c],n=this.$screenRowCache[c],d=e>l[h-1];else var d=!h;for(var u=this.getNextFoldLine(a),f=u?u.start.row:1/0;e>a;){if(a>=f){if(s=u.end.row+1,s>e)break;u=this.getNextFoldLine(s,u),f=u?u.start.row:1/0}else s=a+1;n+=this.getRowLength(a),a=s,d&&(this.$docRowCache.push(a),this.$screenRowCache.push(n))}var p="";u&&a>=f?(p=this.getFoldDisplayLine(u,e,t),r=u.start.row):(p=this.getLine(e).substring(0,t),r=e);var m=0;if(this.$useWrapMode){var g=this.$wrapData[r];if(g){for(var v=0;p.length>=g[v];)n++,v++;p=p.substring(g[v-1]||0,p.length),m=v>0?g.indent:0}}return{row:n,column:m+this.$getStringScreenWidth(p)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(this.$useWrapMode)for(var i=this.$wrapData.length,n=0,r=0,t=this.$foldData[r++],o=t?t.start.row:1/0;i>n;){var s=this.$wrapData[n];e+=s?s.length+1:1,n++,n>o&&(n=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:1/0)}else{e=this.getLength();for(var a=this.$foldData,r=0;ri));o++);return[n,o]})},this.destroy=function(){this.bgTokenizer&&(this.bgTokenizer.setDocument(null),this.bgTokenizer=null),this.$stopWorker()}}).call(f.prototype),e("./edit_session/folding").Folding.call(f.prototype),e("./edit_session/bracket_match").BracketMatch.call(f.prototype),o.defineOptions(f.prototype,"session",{wrap:{set:function(e){if(e&&"off"!=e?"free"==e?e=!0:"printMargin"==e?e=-1:"string"==typeof e&&(e=parseInt(e,10)||!1):e=!1,this.$wrap!=e)if(this.$wrap=e,e){var t="number"==typeof e?e:null;this.setWrapLimitRange(t,t),this.setUseWrapMode(!0)}else this.setUseWrapMode(!1)},get:function(){return this.getUseWrapMode()?-1==this.$wrap?"printMargin":this.getWrapLimitRange().min?this.$wrap:"free":"off"},handlesSet:!0},wrapMethod:{set:function(e){e="auto"==e?"text"!=this.$mode.type:"text"!=e,e!=this.$wrapAsCode&&(this.$wrapAsCode=e,this.$useWrapMode&&(this.$modified=!0,this.$resetRowCache(0),this.$updateWrapData(0,this.getLength()-1)))},initialValue:"auto"},indentedSoftWrap:{initialValue:!0},firstLineNumber:{set:function(){this._signal("changeBreakpoint")},initialValue:1},useWorker:{set:function(e){this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(e){isNaN(e)||this.$tabSize===e||(this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._signal("changeTabSize"))},initialValue:4,handlesSet:!0},overwrite:{set:function(e){this._signal("changeOverwrite")},initialValue:!1},newLineMode:{set:function(e){this.doc.setNewLineMode(e)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(e){this.setMode(e)},get:function(){return this.$modeId}}}),t.EditSession=f}),ace.define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,i){"use strict";var n=e("./lib/lang"),r=e("./lib/oop"),o=e("./range").Range,s=function(){this.$options={}};(function(){this.set=function(e){return r.mixin(this.$options,e),this},this.getOptions=function(){return n.copyObject(this.$options)},this.setOptions=function(e){this.$options=e},this.find=function(e){var t=this.$options,i=this.$matchIterator(e,t);if(!i)return!1;var n=null;return i.forEach(function(e,i,r){if(e.start)n=e;else{var s=e.offset+(r||0);if(n=new o(i,s,i,s+e.length),!e.length&&t.start&&t.start.start&&0!=t.skipCurrent&&n.isEqual(t.start))return n=null,!1}return!0}),n},this.findAll=function(e){var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var i=t.range,r=i?e.getLines(i.start.row,i.end.row):e.doc.getAllLines(),s=[],a=t.re;if(t.$isMultiLine){var l,c=a.length,h=r.length-c;e:for(var d=a.offset||0;h>=d;d++){for(var u=0;c>u;u++)if(-1==r[d+u].search(a[u]))continue e;var f=r[d],p=r[d+c-1],m=f.length-f.match(a[0])[0].length,g=p.match(a[c-1])[0].length;l&&l.end.row===d&&l.end.column>m||(s.push(l=new o(d,m,d+c-1,g)),c>2&&(d=d+c-2))}}else for(var v=0;vv&&s[v].start.columnv&&s[u].end.column>C&&s[u].end.row==i.end.row;)u--;for(s=s.slice(v,u+1),v=0,u=s.length;u>v;v++)s[v].start.row+=i.start.row,s[v].end.row+=i.start.row}return s},this.replace=function(e,t){var i=this.$options,n=this.$assembleRegExp(i);if(i.$isMultiLine)return t;if(n){var r=n.exec(e);if(!r||r[0].length!=e.length)return null;if(t=e.replace(n,t),i.preserveCase){t=t.split("");for(var o=Math.min(e.length,e.length);o--;){var s=e[o];s&&s.toLowerCase()!=s?t[o]=t[o].toUpperCase():t[o]=t[o].toLowerCase()}t=t.join("")}return t}},this.$matchIterator=function(e,t){var i=this.$assembleRegExp(t);if(!i)return!1;var r;if(t.$isMultiLine)var s=i.length,a=function(t,n,a){var l=t.search(i[0]);if(-1!=l){for(var c=1;s>c;c++)if(t=e.getLine(n+c),-1==t.search(i[c]))return;var h=t.match(i[s-1])[0].length,d=new o(n,l,n+s-1,h);return 1==i.offset?(d.start.row--,d.start.column=Number.MAX_VALUE):a&&(d.start.column+=a),r(d)?!0:void 0}};else if(t.backwards)var a=function(e,t,o){for(var s=n.getMatchOffsets(e,i),a=s.length-1;a>=0;a--)if(r(s[a],t,o))return!0};else var a=function(e,t,o){for(var s=n.getMatchOffsets(e,i),a=0;a=s;n--)if(i(e.getLine(n),n))return;if(0!=t.wrap)for(n=a,s=o.row;n>=s;n--)if(i(e.getLine(n),n))return}}:function(i){var n=o.row,r=e.getLine(n).substr(o.column);if(!i(r,n,o.column)){for(n+=1;a>=n;n++)if(i(e.getLine(n),n))return;if(0!=t.wrap)for(n=s,a=o.row;a>=n;n++)if(i(e.getLine(n),n))return}};return{forEach:l}}}).call(s.prototype),t.Search=s}),ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,i){"use strict";function n(e,t){this.platform=t||(s.isMac?"mac":"win"),this.commands={},this.commandKeyBinding={},this.addCommands(e),this.$singleCommand=!0}function r(e,t){n.call(this,e,t),this.$singleCommand=!1}var o=e("../lib/keys"),s=e("../lib/useragent"),a=o.KEY_MODS;r.prototype=n.prototype,function(){function e(e){return"object"==typeof e&&e.bindKey&&e.bindKey.position||0}this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e,t){var i=e&&("string"==typeof e?e:e.name);e=this.commands[i],t||delete this.commands[i]; +var n=this.commandKeyBinding;for(var r in n){var o=n[r];if(o==e)delete n[r];else if(Array.isArray(o)){var s=o.indexOf(e);-1!=s&&(o.splice(s,1),1==o.length&&(n[r]=o[0]))}}},this.bindKey=function(e,t,i){return"object"==typeof e&&e&&(void 0==i&&(i=e.position),e=e[this.platform]),e?"function"==typeof t?this.addCommand({exec:t,bindKey:e,name:t.name||e}):void e.split("|").forEach(function(e){var n="";if(-1!=e.indexOf(" ")){var r=e.split(/\s+/);e=r.pop(),r.forEach(function(e){var t=this.parseKeys(e),i=a[t.hashId]+t.key;n+=(n?" ":"")+i,this._addCommandToBinding(n,"chainKeys")},this),n+=" "}var o=this.parseKeys(e),s=a[o.hashId]+o.key;this._addCommandToBinding(n+s,t,i)},this):void 0},this._addCommandToBinding=function(t,i,n){var r,o=this.commandKeyBinding;if(i)if(!o[t]||this.$singleCommand)o[t]=i;else{Array.isArray(o[t])?-1!=(r=o[t].indexOf(i))&&o[t].splice(r,1):o[t]=[o[t]],"number"!=typeof n&&(n=n||i.isDefault?-100:e(i));var s=o[t];for(r=0;rn)break}s.splice(r,0,i)}else delete o[t]},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var i=e[t];if(i){if("string"==typeof i)return this.bindKey(i,t);"function"==typeof i&&(i={exec:i}),"object"==typeof i&&(i.name||(i.name=t),this.addCommand(i))}},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){this.bindKey(e.bindKey,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(e){return e}),i=t.pop(),n=o[i];if(o.FUNCTION_KEYS[n])i=o.FUNCTION_KEYS[n].toLowerCase();else{if(!t.length)return{key:i,hashId:-1};if(1==t.length&&"shift"==t[0])return{key:i.toUpperCase(),hashId:-1}}for(var r=0,s=t.length;s--;){var a=o.KEY_MODS[t[s]];if(null==a)return"undefined"!=typeof console&&console.error("invalid modifier "+t[s]+" in "+e),!1;r|=a}return{key:i,hashId:r}},this.findKeyCommand=function(e,t){var i=a[e]+t;return this.commandKeyBinding[i]},this.handleKeyboard=function(e,t,i,n){if(!(0>n)){var r=a[t]+i,o=this.commandKeyBinding[r];return e.$keyChain&&(e.$keyChain+=" "+r,o=this.commandKeyBinding[e.$keyChain]||o),!o||"chainKeys"!=o&&"chainKeys"!=o[o.length-1]?(e.$keyChain&&(t&&4!=t||1!=i.length?(-1==t||n>0)&&(e.$keyChain=""):e.$keyChain=e.$keyChain.slice(0,-r.length-1)),{command:o}):(e.$keyChain=e.$keyChain||r,{command:"null"})}},this.getStatusText=function(e,t){return t.$keyChain||""}}.call(n.prototype),t.HashHandler=n,t.MultiHashHandler=r}),ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("../lib/oop"),r=e("../keyboard/hash_handler").MultiHashHandler,o=e("../lib/event_emitter").EventEmitter,s=function(e,t){r.call(this,t,e),this.byName=this.commands,this.setDefaultHandler("exec",function(e){return e.command.exec(e.editor,e.args||{})})};n.inherits(s,r),function(){n.implement(this,o),this.exec=function(e,t,i){if(Array.isArray(e)){for(var n=e.length;n--;)if(this.exec(e[n],t,i))return!0;return!1}if("string"==typeof e&&(e=this.commands[e]),!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;var r={editor:t,command:e,args:i};return r.returnValue=this._emit("exec",r),this._signal("afterExec",r),r.returnValue!==!1},this.toggleRecording=function(e){return this.$inReplay?void 0:(e&&e._emit("changeStatus"),this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0))},this.replay=function(e){if(!this.$inReplay&&this.macro){if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){"string"==typeof t?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}}},this.trimMacro=function(e){return e.map(function(e){return"string"!=typeof e[0]&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(s.prototype),t.CommandManager=s}),ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"],function(e,t,i){"use strict";function n(e,t){return{win:e,mac:t}}var r=e("../lib/lang"),o=e("../config"),s=e("../range").Range;t.commands=[{name:"showSettingsMenu",bindKey:n("Ctrl-,","Command-,"),exec:function(e){o.loadModule("ace/ext/settings_menu",function(t){t.init(e),e.showSettingsMenu()})},readOnly:!0},{name:"goToNextError",bindKey:n("Alt-E","Ctrl-E"),exec:function(e){o.loadModule("ace/ext/error_marker",function(t){t.showErrorMarker(e,1)})},scrollIntoView:"animate",readOnly:!0},{name:"goToPreviousError",bindKey:n("Alt-Shift-E","Ctrl-Shift-E"),exec:function(e){o.loadModule("ace/ext/error_marker",function(t){t.showErrorMarker(e,-1)})},scrollIntoView:"animate",readOnly:!0},{name:"selectall",bindKey:n("Ctrl-A","Command-A"),exec:function(e){e.selectAll()},readOnly:!0},{name:"centerselection",bindKey:n(null,"Ctrl-L"),exec:function(e){e.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:n("Ctrl-L","Command-L"),exec:function(e){var t=parseInt(prompt("Enter line number:"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:"fold",bindKey:n("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(e){e.session.toggleFold(!1)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"unfold",bindKey:n("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(e){e.session.toggleFold(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleFoldWidget",bindKey:n("F2","F2"),exec:function(e){e.session.toggleFoldWidget()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleParentFoldWidget",bindKey:n("Alt-F2","Alt-F2"),exec:function(e){e.session.toggleFoldWidget(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"foldall",bindKey:n(null,"Ctrl-Command-Option-0"),exec:function(e){e.session.foldAll()},scrollIntoView:"center",readOnly:!0},{name:"foldOther",bindKey:n("Alt-0","Command-Option-0"),exec:function(e){e.session.foldAll(),e.session.unfold(e.selection.getAllRanges())},scrollIntoView:"center",readOnly:!0},{name:"unfoldall",bindKey:n("Alt-Shift-0","Command-Option-Shift-0"),exec:function(e){e.session.unfold()},scrollIntoView:"center",readOnly:!0},{name:"findnext",bindKey:n("Ctrl-K","Command-G"),exec:function(e){e.findNext()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"findprevious",bindKey:n("Ctrl-Shift-K","Command-Shift-G"),exec:function(e){e.findPrevious()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"selectOrFindNext",bindKey:n("Alt-K","Ctrl-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findNext()},readOnly:!0},{name:"selectOrFindPrevious",bindKey:n("Alt-Shift-K","Ctrl-Shift-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findPrevious()},readOnly:!0},{name:"find",bindKey:n("Ctrl-F","Command-F"),exec:function(e){o.loadModule("ace/ext/searchbox",function(t){t.Search(e)})},readOnly:!0},{name:"overwrite",bindKey:"Insert",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:n("Ctrl-Shift-Home","Command-Shift-Up"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotostart",bindKey:n("Ctrl-Home","Command-Home|Command-Up"),exec:function(e){e.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectup",bindKey:n("Shift-Up","Shift-Up"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golineup",bindKey:n("Up","Up|Ctrl-P"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttoend",bindKey:n("Ctrl-Shift-End","Command-Shift-Down"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotoend",bindKey:n("Ctrl-End","Command-End|Command-Down"),exec:function(e){e.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectdown",bindKey:n("Shift-Down","Shift-Down"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golinedown",bindKey:n("Down","Down|Ctrl-N"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordleft",bindKey:n("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordleft",bindKey:n("Ctrl-Left","Option-Left"),exec:function(e){e.navigateWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolinestart",bindKey:n("Alt-Shift-Left","Command-Shift-Left"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolinestart",bindKey:n("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(e){e.navigateLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectleft",bindKey:n("Shift-Left","Shift-Left"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoleft",bindKey:n("Left","Left|Ctrl-B"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordright",bindKey:n("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordright",bindKey:n("Ctrl-Right","Option-Right"),exec:function(e){e.navigateWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolineend",bindKey:n("Alt-Shift-Right","Command-Shift-Right"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolineend",bindKey:n("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(e){e.navigateLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectright",bindKey:n("Shift-Right","Shift-Right"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoright",bindKey:n("Right","Right|Ctrl-F"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectpagedown",bindKey:"Shift-PageDown",exec:function(e){e.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:n(null,"Option-PageDown"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:n("PageDown","PageDown|Ctrl-V"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:"Shift-PageUp",exec:function(e){e.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:n(null,"Option-PageUp"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:"PageUp",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:"scrollup",bindKey:n("Ctrl-Up",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",bindKey:n("Ctrl-Down",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",bindKey:"Shift-Home",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectlineend",bindKey:"Shift-End",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"togglerecording",bindKey:n("Ctrl-Alt-E","Command-Option-E"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:"replaymacro",bindKey:n("Ctrl-Shift-E","Command-Shift-E"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:"jumptomatching",bindKey:n("Ctrl-P","Ctrl-P"),exec:function(e){e.jumpToMatching()},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"selecttomatching",bindKey:n("Ctrl-Shift-P","Ctrl-Shift-P"),exec:function(e){e.jumpToMatching(!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"expandToMatching",bindKey:n("Ctrl-Shift-M","Ctrl-Shift-M"),exec:function(e){e.jumpToMatching(!0,!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"passKeysToBrowser",bindKey:n(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:"copy",exec:function(e){},readOnly:!0},{name:"cut",exec:function(e){var t=e.getSelectionRange();e._emit("cut",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"paste",exec:function(e,t){e.$handlePaste(t)},scrollIntoView:"cursor"},{name:"removeline",bindKey:n("Ctrl-D","Command-D"),exec:function(e){e.removeLines()},scrollIntoView:"cursor",multiSelectAction:"forEachLine"},{name:"duplicateSelection",bindKey:n("Ctrl-Shift-D","Command-Shift-D"),exec:function(e){e.duplicateSelection()},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"sortlines",bindKey:n("Ctrl-Alt-S","Command-Alt-S"),exec:function(e){e.sortLines()},scrollIntoView:"selection",multiSelectAction:"forEachLine"},{name:"togglecomment",bindKey:n("Ctrl-/","Command-/"),exec:function(e){e.toggleCommentLines()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"toggleBlockComment",bindKey:n("Ctrl-Shift-/","Command-Shift-/"),exec:function(e){e.toggleBlockComment()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"modifyNumberUp",bindKey:n("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(e){e.modifyNumber(1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"modifyNumberDown",bindKey:n("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(e){e.modifyNumber(-1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"replace",bindKey:n("Ctrl-H","Command-Option-F"),exec:function(e){o.loadModule("ace/ext/searchbox",function(t){t.Search(e,!0)})}},{name:"undo",bindKey:n("Ctrl-Z","Command-Z"),exec:function(e){e.undo()}},{name:"redo",bindKey:n("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(e){e.redo()}},{name:"copylinesup",bindKey:n("Alt-Shift-Up","Command-Option-Up"),exec:function(e){e.copyLinesUp()},scrollIntoView:"cursor"},{name:"movelinesup",bindKey:n("Alt-Up","Option-Up"),exec:function(e){e.moveLinesUp()},scrollIntoView:"cursor"},{name:"copylinesdown",bindKey:n("Alt-Shift-Down","Command-Option-Down"),exec:function(e){e.copyLinesDown()},scrollIntoView:"cursor"},{name:"movelinesdown",bindKey:n("Alt-Down","Option-Down"),exec:function(e){e.moveLinesDown()},scrollIntoView:"cursor"},{name:"del",bindKey:n("Delete","Delete|Ctrl-D|Shift-Delete"),exec:function(e){e.remove("right")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"backspace",bindKey:n("Shift-Backspace|Backspace","Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(e){e.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"cut_or_delete",bindKey:n("Shift-Delete",null),exec:function(e){return e.selection.isEmpty()?void e.remove("left"):!1},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestart",bindKey:n("Alt-Backspace","Command-Backspace"),exec:function(e){e.removeToLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineend",bindKey:n("Alt-Delete","Ctrl-K"),exec:function(e){e.removeToLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordleft",bindKey:n("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(e){e.removeWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordright",bindKey:n("Ctrl-Delete","Alt-Delete"),exec:function(e){e.removeWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"outdent",bindKey:n("Shift-Tab","Shift-Tab"),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"indent",bindKey:n("Tab","Tab"),exec:function(e){e.indent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"blockoutdent",bindKey:n("Ctrl-[","Ctrl-["),exec:function(e){e.blockOutdent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"blockindent",bindKey:n("Ctrl-]","Ctrl-]"),exec:function(e){e.blockIndent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"insertstring",exec:function(e,t){e.insert(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"inserttext",exec:function(e,t){e.insert(r.stringRepeat(t.text||"",t.times||1))},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"splitline",bindKey:n(null,"Ctrl-O"),exec:function(e){e.splitLine()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"transposeletters",bindKey:n("Ctrl-T","Ctrl-T"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)},scrollIntoView:"cursor"},{name:"touppercase",bindKey:n("Ctrl-U","Ctrl-U"),exec:function(e){e.toUpperCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"tolowercase",bindKey:n("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(e){e.toLowerCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"expandtoline",bindKey:n("Ctrl-Shift-L","Command-Shift-L"),exec:function(e){var t=e.selection.getRange();t.start.column=t.end.column=0,t.end.row++,e.selection.setRange(t,!1)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"joinlines",bindKey:n(null,null),exec:function(e){for(var t=e.selection.isBackwards(),i=t?e.selection.getSelectionLead():e.selection.getSelectionAnchor(),n=t?e.selection.getSelectionAnchor():e.selection.getSelectionLead(),o=e.session.doc.getLine(i.row).length,a=e.session.doc.getTextRange(e.selection.getRange()),l=a.replace(/\n\s*/," ").length,c=e.session.doc.getLine(i.row),h=i.row+1;h<=n.row+1;h++){var d=r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(h)));0!==d.length&&(d=" "+d),c+=d}n.row+10?(e.selection.moveCursorTo(i.row,i.column),e.selection.selectTo(i.row,i.column+l)):(o=e.session.doc.getLine(i.row).length>o?o+1:o,e.selection.moveCursorTo(i.row,o))},multiSelectAction:"forEach",readOnly:!0},{name:"invertSelection",bindKey:n(null,null),exec:function(e){var t=e.session.doc.getLength()-1,i=e.session.doc.getLine(t).length,n=e.selection.rangeList.ranges,r=[];n.length<1&&(n=[e.selection.getRange()]);for(var o=0;o0&&this.$blockScrolling--;var i=t&&t.scrollIntoView;if(i){switch(i){case"center-animate":i="animate";case"center":this.renderer.scrollCursorIntoView(null,.5);break;case"animate":case"cursor":this.renderer.scrollCursorIntoView();break;case"selectionPart":var n=this.selection.getRange(),r=this.renderer.layerConfig;(n.start.row>=r.lastRow||n.end.row<=r.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead)}"animate"==i&&this.renderer.animateScrolling(this.curOp.scrollTop)}this.prevOp=this.curOp,this.curOp=null}},this.$mergeableCommands=["backspace","del","insertstring"],this.$historyTracker=function(e){if(this.$mergeUndoDeltas){var t=this.prevOp,i=this.$mergeableCommands,n=t.command&&e.command.name==t.command.name;if("insertstring"==e.command.name){var r=e.args;void 0===this.mergeNextCommand&&(this.mergeNextCommand=!0),n=n&&this.mergeNextCommand&&(!/\s/.test(r)||/\s/.test(t.args)),this.mergeNextCommand=!0}else n=n&&-1!==i.indexOf(e.command.name);"always"!=this.$mergeUndoDeltas&&Date.now()-this.sequenceStartTime>2e3&&(n=!1),n?this.session.mergeUndoDeltas=!0:-1!==i.indexOf(e.command.name)&&(this.sequenceStartTime=Date.now())}},this.setKeyboardHandler=function(e,t){if(e&&"string"==typeof e){this.$keybindingId=e;var i=this;v.loadModule(["keybinding",e],function(n){i.$keybindingId==e&&i.keyBinding.setKeyboardHandler(n&&n.handler),t&&t()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(e),t&&t()},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session!=e){this.curOp&&this.endOperation(),this.curOp={};var t=this.session;if(t){this.session.off("change",this.$onDocumentChange),this.session.off("changeMode",this.$onChangeMode),this.session.off("tokenizerUpdate",this.$onTokenizerUpdate),this.session.off("changeTabSize",this.$onChangeTabSize),this.session.off("changeWrapLimit",this.$onChangeWrapLimit),this.session.off("changeWrapMode",this.$onChangeWrapMode),this.session.off("changeFold",this.$onChangeFold),this.session.off("changeFrontMarker",this.$onChangeFrontMarker),this.session.off("changeBackMarker",this.$onChangeBackMarker),this.session.off("changeBreakpoint",this.$onChangeBreakpoint),this.session.off("changeAnnotation",this.$onChangeAnnotation),this.session.off("changeOverwrite",this.$onCursorChange),this.session.off("changeScrollTop",this.$onScrollTopChange),this.session.off("changeScrollLeft",this.$onScrollLeftChange);var i=this.session.getSelection();i.off("changeCursor",this.$onCursorChange),i.off("changeSelection",this.$onSelectionChange)}this.session=e,e?(this.$onDocumentChange=this.onDocumentChange.bind(this),e.on("change",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.on("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.on("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.on("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.on("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.on("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.on("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.on("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.on("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.on("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.on("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.on("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.on("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.on("changeScrollLeft",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.on("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.on("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(e)),this._signal("changeSession",{session:e,oldSession:t}),this.curOp=null,t&&t._signal("changeEditor",{oldEditor:this}),e&&e._signal("changeEditor",{editor:this})}},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?1==t?this.navigateFileEnd():-1==t&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e,t){this.renderer.setTheme(e,t)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.getFontSize=function(){return this.getOption("fontSize")||r.computedStyle(this.container,"fontSize")},this.setFontSize=function(e){this.setOption("fontSize",e)},this.$highlightBrackets=function(){if(this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null),!this.$highlightPending){var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session;if(t&&t.bgTokenizer){var i=t.findMatchingBracket(e.getCursorPosition());if(i)var n=new f(i.row,i.column,i.row,i.column+1);else if(t.$mode.getMatching)var n=t.$mode.getMatching(e.session);n&&(t.$bracketHighlight=t.addMarker(n,"ace_bracket","text"))}},50)}},this.$highlightTags=function(){if(!this.$highlightTagPending){var e=this;this.$highlightTagPending=!0,setTimeout(function(){e.$highlightTagPending=!1;var t=e.session;if(t&&t.bgTokenizer){var i=e.getCursorPosition(),n=new w(e.session,i.row,i.column),r=n.getCurrentToken();if(!r||!/\b(?:tag-open|tag-name)/.test(r.type))return t.removeMarker(t.$tagHighlight),void(t.$tagHighlight=null);if(-1==r.type.indexOf("tag-open")||(r=n.stepForward())){var o=r.value,s=0,a=n.stepBackward();if("<"==a.value){do a=r,r=n.stepForward(),r&&r.value===o&&-1!==r.type.indexOf("tag-name")&&("<"===a.value?s++:"=0)}else{do r=a,a=n.stepBackward(),r&&r.value===o&&-1!==r.type.indexOf("tag-name")&&("<"===a.value?s++:"=s);n.stepForward()}if(!r)return t.removeMarker(t.$tagHighlight),void(t.$tagHighlight=null);var l=n.getCurrentTokenRow(),c=n.getCurrentTokenColumn(),h=new f(l,c,l,c+r.value.length);t.$tagHighlight&&0!==h.compareRange(t.$backMarkers[t.$tagHighlight].range)&&(t.removeMarker(t.$tagHighlight),t.$tagHighlight=null),h&&!t.$tagHighlight&&(t.$tagHighlight=t.addMarker(h,"ace_bracket","text"))}}},50)}},this.focus=function(){var e=this;setTimeout(function(){e.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(e){this.$isFocused||(this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus",e))},this.onBlur=function(e){this.$isFocused&&(this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur",e))},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(e){var t=this.session.$useWrapMode,i=e.start.row==e.end.row?e.end.row:1/0;this.renderer.updateLines(e.start.row,i,t),this._signal("change",e),this.$cursorChange(),this.$updateHighlightActiveLine()},this.onTokenizerUpdate=function(e){var t=e.data;this.renderer.updateLines(t.first,t.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||(v.warn("Automatically scrolling cursor into view after selection change","this will be disabled in the next version","set editor.$blockScrolling = Infinity to disable this message"),this.renderer.scrollCursorIntoView()),this.$highlightBrackets(),this.$highlightTags(),this.$updateHighlightActiveLine(),this._signal("changeSelection")},this.$updateHighlightActiveLine=function(){var e,t=this.getSession();if(this.$highlightActiveLine&&("line"==this.$selectionStyle&&this.selection.isMultiLine()||(e=this.getCursorPosition()),!this.renderer.$maxLines||1!==this.session.getLength()||this.renderer.$minLines>1||(e=!1)),t.$highlightLineMarker&&!e)t.removeMarker(t.$highlightLineMarker.id),t.$highlightLineMarker=null;else if(!t.$highlightLineMarker&&e){var i=new f(e.row,e.column,e.row,1/0);i.id=t.addMarker(i,"ace_active-line","screenLine"),t.$highlightLineMarker=i}else e&&(t.$highlightLineMarker.start.row=e.row,t.$highlightLineMarker.end.row=e.row,t.$highlightLineMarker.start.column=e.column,t._signal("changeBackMarker"))},this.onSelectionChange=function(e){var t=this.session;if(t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null, +this.selection.isEmpty())this.$updateHighlightActiveLine();else{var i=this.selection.getRange(),n=this.getSelectionStyle();t.$selectionMarker=t.addMarker(i,"ace_selection",n)}var r=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(r),this._signal("changeSelection")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(!t.isEmpty()&&!t.isMultiLine()){var i=t.start.column-1,n=t.end.column+1,r=e.getLine(t.start.row),o=r.length,s=r.substring(Math.max(i,0),Math.min(n,o));if(!(i>=0&&/^[\w\d]/.test(s)||o>=n&&/[\w\d]$/.test(s))&&(s=r.substring(t.start.column,t.end.column),/^[\w\d]+$/.test(s))){var a=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:s});return a}}},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(e){this.renderer.updateText(),this._emit("changeMode",e)},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},this.getCopyText=function(){var e=this.getSelectedText();return this._signal("copy",e),e},this.onCopy=function(){this.commands.exec("copy",this)},this.onCut=function(){this.commands.exec("cut",this)},this.onPaste=function(e,t){var i={text:e,event:t};this.commands.exec("paste",this,i)},this.$handlePaste=function(e){"string"==typeof e&&(e={text:e}),this._signal("paste",e);var t=e.text;if(!this.inMultiSelectMode||this.inVirtualSelectionMode)this.insert(t);else{var i=t.split(/\r\n|\r|\n/),n=this.selection.rangeList.ranges;if(i.length>n.length||i.length<2||!i[1])return this.commands.exec("insertstring",this,t);for(var r=n.length;r--;){var o=n[r];o.isEmpty()||this.session.remove(o),this.session.insert(o.start,i[r])}}},this.execCommand=function(e,t){return this.commands.exec(e,this,t)},this.insert=function(e,t){var i=this.session,n=i.getMode(),r=this.getCursorPosition();if(this.getBehavioursEnabled()&&!t){var o=n.transformAction(i.getState(r.row),"insertion",this,i,e);o&&(e!==o.text&&(this.session.mergeUndoDeltas=!1,this.$mergeNextCommand=!1),e=o.text)}if(" "==e&&(e=this.session.getTabString()),this.selection.isEmpty()){if(this.session.getOverwrite()){var s=new f.fromPoints(r,r);s.end.column+=e.length,this.session.remove(s)}}else{var s=this.getSelectionRange();r=this.session.remove(s),this.clearSelection()}if("\n"==e||"\r\n"==e){var a=i.getLine(r.row);if(r.column>a.search(/\S|$/)){var l=a.substr(r.column).search(/\S|$/);i.doc.removeInLine(r.row,r.column,r.column+l)}}this.clearSelection();var c=r.column,h=i.getState(r.row),a=i.getLine(r.row),d=n.checkOutdent(h,a,e);i.insert(r,e);if(o&&o.selection&&(2==o.selection.length?this.selection.setSelectionRange(new f(r.row,c+o.selection[0],r.row,c+o.selection[1])):this.selection.setSelectionRange(new f(r.row+o.selection[0],o.selection[1],r.row+o.selection[2],o.selection[3]))),i.getDocument().isNewLine(e)){var u=n.getNextLineIndent(h,a.slice(0,r.column),i.getTabString());i.insert({row:r.row+1,column:0},u)}d&&n.autoOutdent(h,i,r.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,i){this.keyBinding.onCommandKey(e,t,i)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.setOption("scrollSpeed",e)},this.getScrollSpeed=function(){return this.getOption("scrollSpeed")},this.setDragDelay=function(e){this.setOption("dragDelay",e)},this.getDragDelay=function(){return this.getOption("dragDelay")},this.setSelectionStyle=function(e){this.setOption("selectionStyle",e)},this.getSelectionStyle=function(){return this.getOption("selectionStyle")},this.setHighlightActiveLine=function(e){this.setOption("highlightActiveLine",e)},this.getHighlightActiveLine=function(){return this.getOption("highlightActiveLine")},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.setHighlightSelectedWord=function(e){this.setOption("highlightSelectedWord",e)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.setReadOnly=function(e){this.setOption("readOnly",e)},this.getReadOnly=function(){return this.getOption("readOnly")},this.setBehavioursEnabled=function(e){this.setOption("behavioursEnabled",e)},this.getBehavioursEnabled=function(){return this.getOption("behavioursEnabled")},this.setWrapBehavioursEnabled=function(e){this.setOption("wrapBehavioursEnabled",e)},this.getWrapBehavioursEnabled=function(){return this.getOption("wrapBehavioursEnabled")},this.setShowFoldWidgets=function(e){this.setOption("showFoldWidgets",e)},this.getShowFoldWidgets=function(){return this.getOption("showFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.remove=function(e){this.selection.isEmpty()&&("left"==e?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var i=this.session,n=i.getState(t.start.row),r=i.getMode().transformAction(n,"deletion",this,i,t);if(0===t.end.column){var o=i.getTextRange(t);if("\n"==o[o.length-1]){var s=i.getLine(t.end.row);/^\s+$/.test(s)&&(t.end.column=s.length)}}r&&(t=r)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(this.selection.isEmpty()){var e=this.getCursorPosition(),t=e.column;if(0!==t){var i,n,r=this.session.getLine(e.row);tt.toLowerCase()?1:0});for(var n=new f(0,0,0,0),r=e.first;r<=e.last;r++){var o=t.getLine(r);n.start.row=r,n.end.row=r,n.end.column=o.length,t.replace(n,i[r-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),i=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,i,e)},this.getNumberAt=function(e,t){var i=/[\-]?[0-9]+(?:\.[0-9]+)?/g;i.lastIndex=0;for(var n=this.session.getLine(e);i.lastIndex=t){var o={value:r[0],start:r.index,end:r.index+r[0].length};return o}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,i=this.selection.getCursor().column,n=new f(t,i-1,t,i),r=this.session.getTextRange(n);if(!isNaN(parseFloat(r))&&isFinite(r)){var o=this.getNumberAt(t,i);if(o){var s=o.value.indexOf(".")>=0?o.start+o.value.indexOf(".")+1:o.end,a=o.start+o.value.length-s,l=parseFloat(o.value);l*=Math.pow(10,a),e*=s!==o.end&&s>i?Math.pow(10,o.end-i-1):Math.pow(10,o.end-i),l+=e,l/=Math.pow(10,a);var c=l.toFixed(a),h=new f(t,o.start,t,o.end);this.session.replace(h,c),this.moveCursorTo(t,Math.max(o.start+1,i+c.length-o.value.length))}}},this.removeLines=function(){var e=this.$getSelectedRows();this.session.removeFullLines(e.first,e.last),this.clearSelection()},this.duplicateSelection=function(){var e=this.selection,t=this.session,i=e.getRange(),n=e.isBackwards();if(i.isEmpty()){var r=i.start.row;t.duplicateLines(r,r)}else{var o=n?i.start:i.end,s=t.insert(o,t.getTextRange(i),!1);i.start=o,i.end=s,e.setSelectionRange(i,n)}},this.moveLinesDown=function(){this.$moveLines(1,!1)},this.moveLinesUp=function(){this.$moveLines(-1,!1)},this.moveText=function(e,t,i){return this.session.moveText(e,t,i)},this.copyLinesUp=function(){this.$moveLines(-1,!0)},this.copyLinesDown=function(){this.$moveLines(1,!0)},this.$moveLines=function(e,t){var i,n,r=this.selection;if(!r.inMultiSelectMode||this.inVirtualSelectionMode){var o=r.toOrientedRange();i=this.$getSelectedRows(o),n=this.session.$moveLines(i.first,i.last,t?0:e),t&&-1==e&&(n=0),o.moveBy(n,0),r.fromOrientedRange(o)}else{var s=r.rangeList.ranges;r.rangeList.detach(this.session),this.inVirtualSelectionMode=!0;for(var a=0,l=0,c=s.length,h=0;c>h;h++){var d=h;s[h].moveBy(a,0),i=this.$getSelectedRows(s[h]);for(var u=i.first,f=i.last;++hf+1)break;f=p.last}for(h--,a=this.session.$moveLines(u,f,t?0:e),t&&-1==e&&(d=h+1);h>=d;)s[d].moveBy(a,0),d++;t||(a=0),l+=a}r.fromOrientedRange(r.ranges[0]),r.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},this.$getSelectedRows=function(e){return e=(e||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(e.start.row),last:this.session.getRowFoldEnd(e.end.row)}},this.onCompositionStart=function(e){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var i=this.renderer,n=this.renderer.layerConfig,r=e*Math.floor(n.height/n.lineHeight);this.$blockScrolling++,t===!0?this.selection.$moveSelection(function(){this.moveCursorBy(r,0)}):t===!1&&(this.selection.moveCursorBy(r,0),this.selection.clearSelection()),this.$blockScrolling--;var o=i.scrollTop;i.scrollBy(0,r*n.lineHeight),null!=t&&i.scrollCursorIntoView(null,.5),i.animateScrolling(o)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,i,n){this.renderer.scrollToLine(e,t,i,n)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e,t){var i=this.getCursorPosition(),n=new w(this.session,i.row,i.column),r=n.getCurrentToken(),o=r||n.stepForward();if(o){var s,a,l=!1,c={},h=i.column-o.start,d={")":"(","(":"(","]":"[","[":"[","{":"{","}":"{"};do{if(o.value.match(/[{}()\[\]]/g)){for(;h=0;--o)this.$tryReplace(i[o],e)&&n++;return this.selection.setSelectionRange(r),this.$blockScrolling-=1,n},this.$tryReplace=function(e,t){var i=this.session.getTextRange(e);return t=this.$search.replace(i,t),null!==t?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,i){t||(t={}),"string"==typeof e||e instanceof RegExp?t.needle=e:"object"==typeof e&&n.mixin(t,e);var r=this.selection.getRange();null==t.needle&&(e=this.session.getTextRange(r)||this.$search.$options.needle,e||(r=this.session.getWordRange(r.start.row,r.start.column),e=this.session.getTextRange(r)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:r});var o=this.$search.find(this.session);return t.preventScroll?o:o?(this.revealRange(o,i),o):(t.backwards?r.start=r.end:r.end=r.start,void this.selection.setRange(r))},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var i=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!==!1&&this.renderer.animateScrolling(i)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy(),this._signal("destroy",this),this.session&&this.session.destroy()},this.setAutoScrollEditorIntoView=function(e){if(e){var t,i=this,n=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement("div"));var r=this.$scrollAnchor;r.style.cssText="position:absolute",this.container.insertBefore(r,this.container.firstChild);var o=this.on("changeSelection",function(){n=!0}),s=this.renderer.on("beforeRender",function(){n&&(t=i.renderer.container.getBoundingClientRect())}),a=this.renderer.on("afterRender",function(){if(n&&t&&(i.isFocused()||i.searchBox&&i.searchBox.isFocused())){var e=i.renderer,o=e.$cursorLayer.$pixelPos,s=e.layerConfig,a=o.top-s.offset;n=o.top>=0&&a+t.top<0?!0:o.topwindow.innerHeight?!1:null,null!=n&&(r.style.top=a+"px",r.style.left=o.left+"px",r.style.height=s.lineHeight+"px",r.scrollIntoView(n)),n=t=null}});this.setAutoScrollEditorIntoView=function(e){e||(delete this.setAutoScrollEditorIntoView,this.off("changeSelection",o),this.renderer.off("afterRender",a),this.renderer.off("beforeRender",s))}}},this.$resetCursorStyle=function(){var e=this.$cursorStyle||"ace",t=this.renderer.$cursorLayer;t&&(t.setSmoothBlinking(/smooth/.test(e)),t.isBlinking=!this.$readOnly&&"wide"!=e,r.setCssClass(t.element,"ace_slim-cursors",/slim/.test(e)))}}).call(y.prototype),v.defineOptions(y.prototype,"editor",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal("changeSelectionStyle",{data:e})},initialValue:"line"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.$resetCursorStyle()},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:["ace","slim","smooth","wide"],initialValue:"ace"},mergeUndoDeltas:{values:[!1,!0,"always"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},keyboardHandler:{set:function(e){this.setKeyboardHandler(e)},get:function(){return this.keybindingId},handlesSet:!0},hScrollBarAlwaysVisible:"renderer",vScrollBarAlwaysVisible:"renderer",highlightGutterLine:"renderer",animatedScroll:"renderer",showInvisibles:"renderer",showPrintMargin:"renderer",printMarginColumn:"renderer",printMargin:"renderer",fadeFoldWidgets:"renderer",showFoldWidgets:"renderer",showLineNumbers:"renderer",showGutter:"renderer",displayIndentGuides:"renderer",fontSize:"renderer",fontFamily:"renderer",maxLines:"renderer",minLines:"renderer",scrollPastEnd:"renderer",fixedWidthGutter:"renderer",theme:"renderer",scrollSpeed:"$mouseHandler",dragDelay:"$mouseHandler",dragEnabled:"$mouseHandler",focusTimout:"$mouseHandler",tooltipFollowsMouse:"$mouseHandler",firstLineNumber:"session",overwrite:"session",newLineMode:"session",useWorker:"session",useSoftTabs:"session",tabSize:"session",wrap:"session",indentedSoftWrap:"session",foldStyle:"session",mode:"session"}),t.Editor=y}),ace.define("ace/undomanager",["require","exports","module"],function(e,t,i){"use strict";var n=function(){this.reset()};(function(){function e(e){return{action:e.action,start:e.start,end:e.end,lines:1==e.lines.length?null:e.lines,text:1==e.lines.length?e.lines[0]:null}}function t(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines||[e.text]}}function i(e,t){for(var i=new Array(e.length),n=0;n0},this.hasRedo=function(){return this.$redoStack.length>0},this.markClean=function(){this.dirtyCounter=0},this.isClean=function(){return 0===this.dirtyCounter},this.$serializeDeltas=function(t){return i(t,e)},this.$deserializeDeltas=function(e){return i(e,t)}}).call(n.prototype),t.UndoManager=n}),ace.define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("../lib/dom"),r=e("../lib/oop"),o=e("../lib/lang"),s=e("../lib/event_emitter").EventEmitter,a=function(e){this.element=n.createElement("div"),this.element.className="ace_layer ace_gutter-layer",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this),this.$cells=[]};(function(){r.implement(this,s),this.setSession=function(e){this.session&&this.session.removeEventListener("change",this.$updateAnnotations),this.session=e,e&&e.on("change",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.addGutterDecoration"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.removeGutterDecoration"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];for(var t=0;ts&&(m=o.end.row+1,o=t.getNextFoldLine(m,o),s=o?o.start.row:1/0),m>r){for(;this.$cells.length>p+1;)f=this.$cells.pop(),this.element.removeChild(f.element);break}f=this.$cells[++p],f||(f={element:null,textNode:null,foldWidget:null},f.element=n.createElement("div"),f.textNode=document.createTextNode(""),f.element.appendChild(f.textNode),this.element.appendChild(f.element),this.$cells[p]=f);var g="ace_gutter-cell ";l[m]&&(g+=l[m]),c[m]&&(g+=c[m]),this.$annotations[m]&&(g+=this.$annotations[m].className),f.element.className!=g&&(f.element.className=g);var v=t.getRowLength(m)*e.lineHeight+"px";if(v!=f.element.style.height&&(f.element.style.height=v),a){var w=a[m];null==w&&(w=a[m]=t.getFoldWidget(m))}if(w){f.foldWidget||(f.foldWidget=n.createElement("span"),f.element.appendChild(f.foldWidget));var g="ace_fold-widget ace_"+w;g+="start"==w&&m==s&&mi.right-t.right?"foldWidgets":void 0}}).call(a.prototype),t.Gutter=a}),ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,t,i){"use strict";var n=e("../range").Range,r=e("../lib/dom"),o=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){function e(e,t,i,n){return(e?1:0)|(t?2:0)|(i?4:0)|(n?8:0)}this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){var e=e||this.config;if(e){this.config=e;var t=[];for(var i in this.markers){var n=this.markers[i];if(n.range){var r=n.range.clipRows(e.firstRow,e.lastRow);if(!r.isEmpty())if(r=r.toScreenRange(this.session),n.renderer){var o=this.$getTop(r.start.row,e),s=this.$padding+r.start.column*e.characterWidth;n.renderer(t,r,s,o,e)}else"fullLine"==n.type?this.drawFullLineMarker(t,r,n.clazz,e):"screenLine"==n.type?this.drawScreenLineMarker(t,r,n.clazz,e):r.isMultiLine()?"text"==n.type?this.drawTextMarker(t,r,n.clazz,e):this.drawMultiLineMarker(t,r,n.clazz,e):this.drawSingleLineMarker(t,r,n.clazz+" ace_start ace_br15",e)}else n.update(t,this,this.session,e)}this.element.innerHTML=t.join("")}},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(t,i,r,o,s){for(var a=this.session,l=i.start.row,c=i.end.row,h=l,d=0,u=0,f=a.getScreenLastRowColumn(h),p=new n(h,i.start.column,h,u);c>=h;h++)p.start.row=p.end.row=h,p.start.column=h==l?i.start.column:a.getRowWrapIndent(h),p.end.column=f,d=u,u=f,f=c>h+1?a.getScreenLastRowColumn(h+1):h==c?0:i.end.column,this.drawSingleLineMarker(t,p,r+(h==l?" ace_start":"")+" ace_br"+e(h==l||h==l+1&&i.start.column,u>d,u>f,h==c),o,h==c?0:1,s)},this.drawMultiLineMarker=function(e,t,i,n,r){var o=this.$padding,s=n.lineHeight,a=this.$getTop(t.start.row,n),l=o+t.start.column*n.characterWidth;r=r||"",e.push("
"),a=this.$getTop(t.end.row,n);var c=t.end.column*n.characterWidth;if(e.push("
"), +s=(t.end.row-t.start.row-1)*n.lineHeight,!(0>=s)){a=this.$getTop(t.start.row+1,n);var h=(t.start.column?1:0)|(t.end.column?0:8);e.push("
")}},this.drawSingleLineMarker=function(e,t,i,n,r,o){var s=n.lineHeight,a=(t.end.column+(r||0)-t.start.column)*n.characterWidth,l=this.$getTop(t.start.row,n),c=this.$padding+t.start.column*n.characterWidth;e.push("
")},this.drawFullLineMarker=function(e,t,i,n,r){var o=this.$getTop(t.start.row,n),s=n.lineHeight;t.start.row!=t.end.row&&(s+=this.$getTop(t.end.row,n)-o),e.push("
")},this.drawScreenLineMarker=function(e,t,i,n,r){var o=this.$getTop(t.start.row,n),s=n.lineHeight;e.push("
")}}).call(o.prototype),t.Marker=o}),ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("../lib/oop"),r=e("../lib/dom"),o=e("../lib/lang"),s=(e("../lib/useragent"),e("../lib/event_emitter").EventEmitter),a=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this)};(function(){n.implement(this,s),this.EOF_CHAR="¶",this.EOL_CHAR_LF="¬",this.EOL_CHAR_CRLF="¤",this.EOL_CHAR=this.EOL_CHAR_LF,this.TAB_CHAR="—",this.SPACE_CHAR="·",this.$padding=0,this.$updateEolChar=function(){var e="\n"==this.session.doc.getNewLineCharacter()?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;return this.EOL_CHAR!=e?(this.EOL_CHAR=e,!0):void 0},this.setPadding=function(e){this.$padding=e,this.element.style.padding="0 "+e+"px"},this.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},this.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},this.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on("changeCharacterSize",function(e){this._signal("changeCharacterSize",e)}.bind(this)),this.$pollSizeChanges()},this.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},this.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},this.setSession=function(e){this.session=e,e&&this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;for(var t=this.$tabStrings=[0],i=1;e+1>i;i++)this.showInvisibles?t.push(""+o.stringRepeat(this.TAB_CHAR,i)+""):t.push(o.stringRepeat(" ",i));if(this.displayIndentGuides){this.$indentGuideRe=/\s\S| \t|\t |\s$/;var n="ace_indent-guide",r="",s="";if(this.showInvisibles){n+=" ace_invisible",r=" ace_invisible_space",s=" ace_invisible_tab";var a=o.stringRepeat(this.SPACE_CHAR,this.tabSize),l=o.stringRepeat(this.TAB_CHAR,this.tabSize)}else var a=o.stringRepeat(" ",this.tabSize),l=a;this.$tabStrings[" "]=""+a+"",this.$tabStrings[" "]=""+l+""}},this.updateLines=function(e,t,i){this.config.lastRow==e.lastRow&&this.config.firstRow==e.firstRow||this.scrollLines(e),this.config=e;for(var n=Math.max(t,e.firstRow),r=Math.min(i,e.lastRow),o=this.element.childNodes,s=0,a=e.firstRow;n>a;a++){var l=this.session.getFoldLine(a);if(l){if(l.containsRow(n)){n=l.start.row;break}a=l.end.row}s++}for(var a=n,l=this.session.getNextFoldLine(a),c=l?l.start.row:1/0;;){if(a>c&&(a=l.end.row+1,l=this.session.getNextFoldLine(a,l),c=l?l.start.row:1/0),a>r)break;var h=o[s++];if(h){var d=[];this.$renderLine(d,a,!this.$useLineGroups(),a==c?l:!1),h.style.height=e.lineHeight*this.session.getRowLength(a)+"px",h.innerHTML=d.join("")}a++}},this.scrollLines=function(e){var t=this.config;if(this.config=e,!t||t.lastRow0;n--)i.removeChild(i.firstChild);if(t.lastRow>e.lastRow)for(var n=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);n>0;n--)i.removeChild(i.lastChild);if(e.firstRowt.lastRow){var r=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);i.appendChild(r)}},this.$renderLinesFragment=function(e,t,i){for(var n=this.element.ownerDocument.createDocumentFragment(),o=t,s=this.session.getNextFoldLine(o),a=s?s.start.row:1/0;;){if(o>a&&(o=s.end.row+1,s=this.session.getNextFoldLine(o,s),a=s?s.start.row:1/0),o>i)break;var l=r.createElement("div"),c=[];if(this.$renderLine(c,o,!1,o==a?s:!1),l.innerHTML=c.join(""),this.$useLineGroups())l.className="ace_line_group",n.appendChild(l),l.style.height=e.lineHeight*this.session.getRowLength(o)+"px";else for(;l.firstChild;)n.appendChild(l.firstChild);o++}return n},this.update=function(e){this.config=e;for(var t=[],i=e.firstRow,n=e.lastRow,r=i,o=this.session.getNextFoldLine(r),s=o?o.start.row:1/0;;){if(r>s&&(r=o.end.row+1,o=this.session.getNextFoldLine(r,o),s=o?o.start.row:1/0),r>n)break;this.$useLineGroups()&&t.push("
"),this.$renderLine(t,r,!1,r==s?o:!1),this.$useLineGroups()&&t.push("
"),r++}this.element.innerHTML=t.join("")},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,i,n){var r=this,s=/\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g,a=function(e,i,n,s,a){if(i)return r.showInvisibles?""+o.stringRepeat(r.SPACE_CHAR,e.length)+"":e;if("&"==e)return"&";if("<"==e)return"<";if(">"==e)return">";if(" "==e){var l=r.session.getScreenTabSize(t+s);return t+=l-1,r.$tabStrings[l]}if(" "==e){var c=r.showInvisibles?"ace_cjk ace_invisible ace_invisible_space":"ace_cjk",h=r.showInvisibles?r.SPACE_CHAR:"";return t+=1,""+h+""}return n?""+r.SPACE_CHAR+"":(t+=1,""+e+"")},l=n.replace(s,a);if(this.$textToken[i.type])e.push(l);else{var c="ace_"+i.type.replace(/\./g," ace_"),h="";"fold"==i.type&&(h=" style='width:"+i.value.length*this.config.characterWidth+"px;' "),e.push("",l,"")}return t+n.length},this.renderIndentGuide=function(e,t,i){var n=t.search(this.$indentGuideRe);return 0>=n||n>=i?t:" "==t[0]?(n-=n%this.tabSize,e.push(o.stringRepeat(this.$tabStrings[" "],n/this.tabSize)),t.substr(n)):" "==t[0]?(e.push(o.stringRepeat(this.$tabStrings[" "],n)),t.substr(n)):t},this.$renderWrappedLine=function(e,t,i,n){for(var r=0,s=0,a=i[0],l=0,c=0;c=a;)l=this.$renderToken(e,l,h,d.substring(0,a-r)),d=d.substring(a-r),r=a,n||e.push("
","
"),e.push(o.stringRepeat(" ",i.indent)),s++,l=0,a=i[s]||Number.MAX_VALUE;0!=d.length&&(r+=d.length,l=this.$renderToken(e,l,h,d))}}},this.$renderSimpleLine=function(e,t){var i=0,n=t[0],r=n.value;this.displayIndentGuides&&(r=this.renderIndentGuide(e,r)),r&&(i=this.$renderToken(e,i,n,r));for(var o=1;o"),r.length){var o=this.session.getRowSplitData(t);o&&o.length?this.$renderWrappedLine(e,r,o,i):this.$renderSimpleLine(e,r)}this.showInvisibles&&(n&&(t=n.end.row),e.push("",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,"")),i||e.push("
")},this.$getFoldLineTokens=function(e,t){function i(e,t,i){for(var n=0,o=0;o+e[n].value.lengthi-t&&(s=s.substring(0,i-t)),r.push({type:e[n].type,value:s}),o=t+s.length,n+=1}for(;i>o&&ni?r.push({type:e[n].type,value:s.substring(0,i-o)}):r.push(e[n]),o+=s.length,n+=1}}var n=this.session,r=[],o=n.getTokens(e);return t.walk(function(e,t,s,a,l){null!=e?r.push({type:"fold",value:e}):(l&&(o=n.getTokens(t)),o.length&&i(o,a,s))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,t,i){"use strict";var n,r=e("../lib/dom"),o=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),void 0===n&&(n=!("opacity"in this.element.style)),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors"),this.$updateCursors=(n?this.$updateVisibility:this.$updateOpacity).bind(this)};(function(){this.$updateVisibility=function(e){for(var t=this.cursors,i=t.length;i--;)t[i].style.visibility=e?"":"hidden"},this.$updateOpacity=function(e){for(var t=this.cursors,i=t.length;i--;)t[i].style.opacity=e?"":"0"},this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e==this.smoothBlinking||n||(this.smoothBlinking=e,r.setCssClass(this.element,"ace_smooth-blinking",e),this.$updateCursors(!0),this.$updateCursors=this.$updateOpacity.bind(this),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.restartTimer=function(){var e=this.$updateCursors;if(clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,"ace_smooth-blinking"),e(!0),this.isBlinking&&this.blinkInterval&&this.isVisible){this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,"ace_smooth-blinking")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){e(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){e(!0),t()},this.blinkInterval),t()}},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var i=this.session.documentToScreenPosition(e),n=this.$padding+i.column*this.config.characterWidth,r=(i.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:n,top:r}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,i=0,n=0;void 0!==t&&0!==t.length||(t=[{cursor:null}]);for(var i=0,r=t.length;r>i;i++){var o=this.getPixelPosition(t[i].cursor,!0);if(!((o.top>e.height+e.offset||o.top<0)&&i>1)){var s=(this.cursors[n++]||this.addCursor()).style;this.drawCursor?this.drawCursor(s,o,e,t[i],this.session):(s.left=o.left+"px",s.top=o.top+"px",s.width=e.characterWidth+"px",s.height=e.lineHeight+"px")}}for(;this.cursors.length>n;)this.removeCursor();var a=this.session.getOverwrite();this.$setOverwrite(a),this.$pixelPos=o,this.restartTimer()},this.drawCursor=null,this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(o.prototype),t.Cursor=o}),ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/dom"),o=e("./lib/event"),s=e("./lib/event_emitter").EventEmitter,a=function(e){this.element=r.createElement("div"),this.element.className="ace_scrollbar ace_scrollbar"+this.classSuffix,this.inner=r.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,o.addListener(this.element,"scroll",this.onScroll.bind(this)),o.addListener(this.element,"mousedown",o.preventDefault)};(function(){n.implement(this,s),this.setVisible=function(e){this.element.style.display=e?"":"none",this.isVisible=e}}).call(a.prototype);var l=function(e,t){a.call(this,e),this.scrollTop=0,t.$scrollbarWidth=this.width=r.scrollbarWidth(e.ownerDocument),this.inner.style.width=this.element.style.width=(this.width||15)+5+"px"};n.inherits(l,a),function(){this.classSuffix="-v",this.onScroll=function(){this.skipEvent||(this.scrollTop=this.element.scrollTop,this._emit("scroll",{data:this.scrollTop})),this.skipEvent=!1},this.getWidth=function(){return this.isVisible?this.width:0},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=function(e){this.inner.style.height=e+"px"},this.setScrollHeight=function(e){this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=this.element.scrollTop=e)}}.call(l.prototype);var c=function(e,t){a.call(this,e),this.scrollLeft=0,this.height=t.$scrollbarWidth,this.inner.style.height=this.element.style.height=(this.height||15)+5+"px"};n.inherits(c,a),function(){this.classSuffix="-h",this.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit("scroll",{data:this.scrollLeft})),this.skipEvent=!1},this.getHeight=function(){return this.isVisible?this.height:0},this.setWidth=function(e){this.element.style.width=e+"px"},this.setInnerWidth=function(e){this.inner.style.width=e+"px"},this.setScrollWidth=function(e){this.inner.style.width=e+"px"},this.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)}}.call(c.prototype),t.ScrollBar=l,t.ScrollBarV=l,t.ScrollBarH=c,t.VScrollBar=l,t.HScrollBar=c}),ace.define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,t,i){"use strict";var n=e("./lib/event"),r=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){if(this.changes=this.changes|e,!this.pending&&this.changes){this.pending=!0;var t=this;n.nextFrame(function(){t.pending=!1;for(var e;e=t.changes;)t.changes=0,t.onRender(e)},this.window)}}}).call(r.prototype),t.RenderLoop=r}),ace.define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,i){var n=e("../lib/oop"),r=e("../lib/dom"),o=e("../lib/lang"),s=e("../lib/useragent"),a=e("../lib/event_emitter").EventEmitter,l=0,c=t.FontMetrics=function(e){this.el=r.createElement("div"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=r.createElement("div"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=r.createElement("div"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),l||this.$testFractionalRect(),this.$measureNode.innerHTML=o.stringRepeat("X",l),this.$characterSize={width:0,height:0},this.checkForSizeChanges()};(function(){n.implement(this,a),this.$characterSize={width:0,height:0},this.$testFractionalRect=function(){var e=r.createElement("div");this.$setMeasureNodeStyles(e.style),e.style.width="0.2px",document.documentElement.appendChild(e);var t=e.getBoundingClientRect().width;l=t>0&&1>t?50:100,e.parentNode.removeChild(e)},this.$setMeasureNodeStyles=function(e,t){e.width=e.height="auto",e.left=e.top="0px",e.visibility="hidden",e.position="absolute",e.whiteSpace="pre",s.isIE<8?e["font-family"]="inherit":e.font="inherit",e.overflow=t?"hidden":"visible"},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight="bold";var t=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=e,this.charSizes=Object.create(null),this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit("changeCharacterSize",{data:e})}},this.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer)return this.$pollSizeChangesTimer;var e=this;return this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.setPolling=function(e){e?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},this.$measureSizes=function(){if(50===l){var e=null;try{e=this.$measureNode.getBoundingClientRect()}catch(t){e={width:0,height:0}}var i={height:e.height,width:e.width/l}}else var i={height:this.$measureNode.clientHeight,width:this.$measureNode.clientWidth/l};return 0===i.width||0===i.height?null:i},this.$measureCharWidth=function(e){this.$main.innerHTML=o.stringRepeat(e,l);var t=this.$main.getBoundingClientRect();return t.width/l},this.getCharacterWidth=function(e){var t=this.charSizes[e];return void 0===t&&(t=this.charSizes[e]=this.$measureCharWidth(e)/this.$characterSize.width),t},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)}}).call(c.prototype)}),ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"],function(e,t,i){"use strict";var n=e("./lib/oop"),r=e("./lib/dom"),o=e("./config"),s=e("./lib/useragent"),a=e("./layer/gutter").Gutter,l=e("./layer/marker").Marker,c=e("./layer/text").Text,h=e("./layer/cursor").Cursor,d=e("./scrollbar").HScrollBar,u=e("./scrollbar").VScrollBar,f=e("./renderloop").RenderLoop,p=e("./layer/font_metrics").FontMetrics,m=e("./lib/event_emitter").EventEmitter,g='.ace_editor { position: relative; overflow: hidden; font: 12px/normal \'Monaco\', \'Menlo\', \'Ubuntu Mono\', \'Consolas\', \'source-code-pro\', monospace; direction: ltr; } .ace_scroller { position: absolute; overflow: hidden; top: 0; bottom: 0; background-color: inherit; -ms-user-select: none; -moz-user-select: none; -webkit-user-select: none; user-select: none; cursor: text; } .ace_content { position: absolute; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; min-width: 100%; } .ace_dragging .ace_scroller:before{ position: absolute; top: 0; left: 0; right: 0; bottom: 0; content: \'\'; background: rgba(250, 250, 250, 0.01); z-index: 1000; } .ace_dragging.ace_dark .ace_scroller:before{ background: rgba(0, 0, 0, 0.01); } .ace_selecting, .ace_selecting * { cursor: text !important; } .ace_gutter { position: absolute; overflow : hidden; width: auto; top: 0; bottom: 0; left: 0; cursor: default; z-index: 4; -ms-user-select: none; -moz-user-select: none; -webkit-user-select: none; user-select: none; } .ace_gutter-active-line { position: absolute; left: 0; right: 0; } .ace_scroller.ace_scroll-left { box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset; } .ace_gutter-cell { padding-left: 19px; padding-right: 6px; background-repeat: no-repeat; } .ace_gutter-cell.ace_error { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg=="); background-repeat: no-repeat; background-position: 2px center; } .ace_gutter-cell.ace_warning { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg=="); background-position: 2px center; } .ace_gutter-cell.ace_info { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII="); background-position: 2px center; } .ace_dark .ace_gutter-cell.ace_info { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC"); } .ace_scrollbar { position: absolute; right: 0; bottom: 0; z-index: 6; } .ace_scrollbar-inner { position: absolute; cursor: text; left: 0; top: 0; } .ace_scrollbar-v{ overflow-x: hidden; overflow-y: scroll; top: 0; } .ace_scrollbar-h { overflow-x: scroll; overflow-y: hidden; left: 0; } .ace_print-margin { position: absolute; height: 100%; } .ace_text-input { position: absolute; z-index: 0; width: 0.5em; height: 1em; opacity: 0; background: transparent; -moz-appearance: none; appearance: none; border: none; resize: none; outline: none; overflow: hidden; font: inherit; padding: 0 1px; margin: 0 -1px; text-indent: -1em; -ms-user-select: text; -moz-user-select: text; -webkit-user-select: text; user-select: text; white-space: pre!important; } .ace_text-input.ace_composition { background: inherit; color: inherit; z-index: 1000; opacity: 1; text-indent: 0; } .ace_layer { z-index: 1; position: absolute; overflow: hidden; word-wrap: normal; white-space: pre; height: 100%; width: 100%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; pointer-events: none; } .ace_gutter-layer { position: relative; width: auto; text-align: right; pointer-events: auto; } .ace_text-layer { font: inherit !important; } .ace_cjk { display: inline-block; text-align: center; } .ace_cursor-layer { z-index: 4; } .ace_cursor { z-index: 4; position: absolute; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; border-left: 2px solid; transform: translatez(0); } .ace_slim-cursors .ace_cursor { border-left-width: 1px; } .ace_overwrite-cursors .ace_cursor { border-left-width: 0; border-bottom: 1px solid; } .ace_hidden-cursors .ace_cursor { opacity: 0.2; } .ace_smooth-blinking .ace_cursor { -webkit-transition: opacity 0.18s; transition: opacity 0.18s; } .ace_editor.ace_multiselect .ace_cursor { border-left-width: 1px; } .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack { position: absolute; z-index: 3; } .ace_marker-layer .ace_selection { position: absolute; z-index: 5; } .ace_marker-layer .ace_bracket { position: absolute; z-index: 6; } .ace_marker-layer .ace_active-line { position: absolute; z-index: 2; } .ace_marker-layer .ace_selected-word { position: absolute; z-index: 4; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } .ace_line .ace_fold { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; display: inline-block; height: 11px; margin-top: -2px; vertical-align: middle; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII="); background-repeat: no-repeat, repeat-x; background-position: center center, top left; color: transparent; border: 1px solid black; border-radius: 2px; cursor: pointer; pointer-events: auto; } .ace_dark .ace_fold { } .ace_fold:hover{ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC"); } .ace_tooltip { background-color: #FFF; background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1)); background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1)); border: 1px solid gray; border-radius: 1px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); color: black; max-width: 100%; padding: 3px 4px; position: fixed; z-index: 999999; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; cursor: default; white-space: pre; word-wrap: break-word; line-height: normal; font-style: normal; font-weight: normal; letter-spacing: normal; pointer-events: none; } .ace_folding-enabled > .ace_gutter-cell { padding-right: 13px; } .ace_fold-widget { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; margin: 0 -12px 0 1px; display: none; width: 11px; vertical-align: top; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg=="); background-repeat: no-repeat; background-position: center; border-radius: 3px; border: 1px solid transparent; cursor: pointer; } .ace_folding-enabled .ace_fold-widget { display: inline-block; } .ace_fold-widget.ace_end { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg=="); } .ace_fold-widget.ace_closed { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA=="); } .ace_fold-widget:hover { border: 1px solid rgba(0, 0, 0, 0.3); background-color: rgba(255, 255, 255, 0.2); box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7); } .ace_fold-widget:active { border: 1px solid rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.05); box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); } .ace_dark .ace_fold-widget { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC"); } .ace_dark .ace_fold-widget.ace_end { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg=="); } .ace_dark .ace_fold-widget.ace_closed { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg=="); } .ace_dark .ace_fold-widget:hover { box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); background-color: rgba(255, 255, 255, 0.1); } .ace_dark .ace_fold-widget:active { box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); } .ace_fold-widget.ace_invalid { background-color: #FFB4B4; border-color: #DE5555; } .ace_fade-fold-widgets .ace_fold-widget { -webkit-transition: opacity 0.4s ease 0.05s; transition: opacity 0.4s ease 0.05s; opacity: 0; } .ace_fade-fold-widgets:hover .ace_fold-widget { -webkit-transition: opacity 0.05s ease 0.05s; transition: opacity 0.05s ease 0.05s; opacity:1; } .ace_underline { text-decoration: underline; } .ace_bold { font-weight: bold; } .ace_nobold .ace_bold { font-weight: normal; } .ace_italic { font-style: italic; } .ace_error-marker { background-color: rgba(255, 0, 0,0.2); position: absolute; z-index: 9; } .ace_highlight-marker { background-color: rgba(255, 255, 0,0.2); position: absolute; z-index: 8; } .ace_br1 {border-top-left-radius : 3px;} .ace_br2 {border-top-right-radius : 3px;} .ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;} .ace_br4 {border-bottom-right-radius: 3px;} .ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;} .ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;} .ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;} .ace_br8 {border-bottom-left-radius : 3px;} .ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;} .ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;} .ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;} .ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} .ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} .ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} .ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;} '; +r.importCssString(g,"ace_editor.css");var v=function(e,t){var i=this;this.container=e||r.createElement("div"),this.$keepTextAreaAtCursor=!s.isOldIE,r.addCssClass(this.container,"ace_editor"),this.setTheme(t),this.$gutter=r.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=r.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=r.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new a(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new l(this.content);var n=this.$textLayer=new c(this.content);this.canvas=n.element,this.$markerFront=new l(this.content),this.$cursorLayer=new h(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new u(this.container,this),this.scrollBarH=new d(this.container,this),this.scrollBarV.addEventListener("scroll",function(e){i.$scrollAnimation||i.session.setScrollTop(e.data-i.scrollMargin.top)}),this.scrollBarH.addEventListener("scroll",function(e){i.$scrollAnimation||i.session.setScrollLeft(e.data-i.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new p(this.container),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.addEventListener("changeCharacterSize",function(e){i.updateCharacterSize(),i.onResize(!0,i.gutterWidth,i.$size.width,i.$size.height),i._signal("changeCharacterSize",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$loop=new f(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),o.resetOptions(this),o._emit("renderer",this)};(function(){this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,n.implement(this,m),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session&&this.session.doc.off("changeNewLineMode",this.onChangeNewLineMode),this.session=e,e&&this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e),e&&(this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on("changeNewLineMode",this.onChangeNewLineMode))},this.updateLines=function(e,t,i){if(void 0===t&&(t=1/0),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRowthis.layerConfig.lastRow||this.$loop.schedule(this.CHANGE_LINES)},this.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar()},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.$changes=0,this.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},this.onResize=function(e,t,i,n){if(!(this.resizing>2)){this.resizing>0?this.resizing++:this.resizing=e?1:0;var r=this.container;n||(n=r.clientHeight||r.scrollHeight),i||(i=r.clientWidth||r.scrollWidth);var o=this.$updateCachedSize(e,t,i,n);if(!this.$size.scrollerHeight||!i&&!n)return this.resizing=0;e&&(this.$gutterLayer.$padding=null),e?this.$renderChanges(o|this.$changes,!0):this.$loop.schedule(o|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarV.scrollLeft=this.scrollBarV.scrollTop=null}},this.$updateCachedSize=function(e,t,i,n){n-=this.$extraHeight||0;var r=0,o=this.$size,s={width:o.width,height:o.height,scrollerHeight:o.scrollerHeight,scrollerWidth:o.scrollerWidth};return n&&(e||o.height!=n)&&(o.height=n,r|=this.CHANGE_SIZE,o.scrollerHeight=o.height,this.$horizScroll&&(o.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+"px",r|=this.CHANGE_SCROLL),i&&(e||o.width!=i)&&(r|=this.CHANGE_SIZE,o.width=i,null==t&&(t=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=t,this.scrollBarH.element.style.left=this.scroller.style.left=t+"px",o.scrollerWidth=Math.max(0,i-t-this.scrollBarV.getWidth()),this.scrollBarH.element.style.right=this.scroller.style.right=this.scrollBarV.getWidth()+"px",this.scroller.style.bottom=this.scrollBarH.getHeight()+"px",(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)&&(r|=this.CHANGE_FULL)),o.$dirty=!i||!n,r&&this._signal("resize",s),r},this.onGutterResize=function(){var e=this.$showGutter?this.$gutter.offsetWidth:0;e!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,e,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):(this.$computeLayerConfig(),this.$loop.schedule(this.CHANGE_MARKER))},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-2*this.$padding,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t,this.$showPrintMargin&&this.$printMarginColumn)},this.setAnimatedScroll=function(e){this.setOption("animatedScroll",e)},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.setOption("showInvisibles",e)},this.getShowInvisibles=function(){return this.getOption("showInvisibles")},this.getDisplayIndentGuides=function(){return this.getOption("displayIndentGuides")},this.setDisplayIndentGuides=function(e){this.setOption("displayIndentGuides",e)},this.setShowPrintMargin=function(e){this.setOption("showPrintMargin",e)},this.getShowPrintMargin=function(){return this.getOption("showPrintMargin")},this.setPrintMarginColumn=function(e){this.setOption("printMarginColumn",e)},this.getPrintMarginColumn=function(){return this.getOption("printMarginColumn")},this.getShowGutter=function(){return this.getOption("showGutter")},this.setShowGutter=function(e){return this.setOption("showGutter",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.$updateGutterLineHighlight=function(){var e=this.$cursorLayer.$pixelPos,t=this.layerConfig.lineHeight;if(this.session.getUseWrapMode()){var i=this.session.selection.getCursor();i.column=0,e=this.$cursorLayer.getPixelPosition(i,!0),t*=this.session.getRowLength(i.row)}this.$gutterLineHighlight.style.top=e.top-this.layerConfig.offset+"px",this.$gutterLineHighlight.style.height=t+"px"},this.$updatePrintMargin=function(){if(this.$showPrintMargin||this.$printMarginEl){if(!this.$printMarginEl){var e=r.createElement("div");e.className="ace_layer ace_print-margin-layer",this.$printMarginEl=r.createElement("div"),this.$printMarginEl.className="ace_print-margin",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",t.visibility=this.$showPrintMargin?"visible":"hidden",this.session&&-1==this.session.$wrap&&this.adjustWrapLimit()}},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.scroller},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(this.$keepTextAreaAtCursor){var e=this.layerConfig,t=this.$cursorLayer.$pixelPos.top,i=this.$cursorLayer.$pixelPos.left;t-=e.offset;var n=this.textarea.style,r=this.lineHeight;if(0>t||t>e.height-r)return void(n.top=n.left="0");var o=this.characterWidth;if(this.$composition){var s=this.textarea.value.replace(/^\x01+/,"");o*=this.session.$getStringScreenWidth(s)[0]+2,r+=2}i-=this.scrollLeft,i>this.$size.scrollerWidth-o&&(i=this.$size.scrollerWidth-o),i+=this.gutterWidth,n.height=r+"px",n.width=o+"px",n.left=Math.min(i,this.$size.scrollerWidth-o)+"px",n.top=Math.min(t,this.$size.height-r)+"px"}},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(0===this.layerConfig.offset?0:1)},this.getLastFullyVisibleRow=function(){var e=this.layerConfig,t=e.lastRow,i=this.session.documentToScreenRow(t,0)*e.lineHeight;return i-this.session.getScrollTop()>e.height-e.lineHeight?t-1:t},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.setScrollMargin=function(e,t,i,n){var r=this.scrollMargin;r.top=0|e,r.bottom=0|t,r.right=0|n,r.left=0|i,r.v=r.top+r.bottom,r.h=r.left+r.right,r.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-r.top),this.updateFull()},this.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.setOption("hScrollBarAlwaysVisible",e)},this.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},this.setVScrollBarAlwaysVisible=function(e){this.setOption("vScrollBarAlwaysVisible",e)},this.$updateScrollBarV=function(){var e=this.layerConfig.maxHeight,t=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(e-=(t-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>e-t&&(e=this.scrollTop+t,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(e+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},this.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},this.$frozen=!1,this.freeze=function(){this.$frozen=!0},this.unfreeze=function(){this.$frozen=!1},this.$renderChanges=function(e,t){if(this.$changes&&(e|=this.$changes,this.$changes=0),!this.session||!this.container.offsetWidth||this.$frozen||!e&&!t)return void(this.$changes|=e);if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal("beforeRender");var i=this.layerConfig;if(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL){if(e|=this.$computeLayerConfig(),i.firstRow!=this.layerConfig.firstRow&&i.firstRowScreen==this.layerConfig.firstRowScreen){var n=this.scrollTop+(i.firstRow-this.layerConfig.firstRow)*this.lineHeight;n>0&&(this.scrollTop=n,e|=this.CHANGE_SCROLL,e|=this.$computeLayerConfig())}i=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),this.$gutterLayer.element.style.marginTop=-i.offset+"px",this.content.style.marginTop=-i.offset+"px",this.content.style.width=i.width+2*this.$padding+"px",this.content.style.height=i.minHeight+"px"}return e&this.CHANGE_H_SCROLL&&(this.content.style.marginLeft=-this.scrollLeft+"px",this.scroller.className=this.scrollLeft<=0?"ace_scroller":"ace_scroller ace_scroll-left"),e&this.CHANGE_FULL?(this.$textLayer.update(i),this.$showGutter&&this.$gutterLayer.update(i),this.$markerBack.update(i),this.$markerFront.update(i),this.$cursorLayer.update(i),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),void this._signal("afterRender")):e&this.CHANGE_SCROLL?(e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(i):this.$textLayer.scrollLines(i),this.$showGutter&&this.$gutterLayer.update(i),this.$markerBack.update(i),this.$markerFront.update(i),this.$cursorLayer.update(i),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this.$moveTextAreaToCursor(),void this._signal("afterRender")):(e&this.CHANGE_TEXT?(this.$textLayer.update(i),this.$showGutter&&this.$gutterLayer.update(i)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(i):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.$showGutter&&this.$gutterLayer.update(i),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(i),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(i),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(i),void this._signal("afterRender"))},this.$autosize=function(){var e=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,i=Math.max((this.$minLines||1)*this.lineHeight,Math.min(t,e))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(i+=this.scrollBarH.getHeight());var n=e>t;if(i!=this.desiredHeight||this.$size.height!=this.desiredHeight||n!=this.$vScroll){n!=this.$vScroll&&(this.$vScroll=n,this.scrollBarV.setVisible(n));var r=this.container.clientWidth;this.container.style.height=i+"px",this.$updateCachedSize(!0,this.$gutterWidth,r,i),this.desiredHeight=i,this._signal("autosize")}},this.$computeLayerConfig=function(){var e=this.session,t=this.$size,i=t.height<=2*this.lineHeight,n=this.session.getScreenLength(),r=n*this.lineHeight,o=this.$getLongestLine(),s=!i&&(this.$hScrollBarAlwaysVisible||t.scrollerWidth-o-2*this.$padding<0),a=this.$horizScroll!==s;a&&(this.$horizScroll=s,this.scrollBarH.setVisible(s));var l=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var c=this.scrollTop%this.lineHeight,h=t.scrollerHeight+this.lineHeight,d=!this.$maxLines&&this.$scrollPastEnd?(t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;r+=d;var u=this.scrollMargin;this.session.setScrollTop(Math.max(-u.top,Math.min(this.scrollTop,r-t.scrollerHeight+u.bottom))),this.session.setScrollLeft(Math.max(-u.left,Math.min(this.scrollLeft,o+2*this.$padding-t.scrollerWidth+u.right)));var f=!i&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-r+d<0||this.scrollTop>u.top),p=l!==f;p&&(this.$vScroll=f,this.scrollBarV.setVisible(f));var m,g,v=Math.ceil(h/this.lineHeight)-1,w=Math.max(0,Math.round((this.scrollTop-c)/this.lineHeight)),y=w+v,A=this.lineHeight;w=e.screenToDocumentRow(w,0);var C=e.getFoldLine(w);C&&(w=C.start.row),m=e.documentToScreenRow(w,0),g=e.getRowLength(w)*A,y=Math.min(e.screenToDocumentRow(y,0),e.getLength()-1),h=t.scrollerHeight+e.getRowLength(y)*A+g,c=this.scrollTop-m*A;var E=0;return this.layerConfig.width!=o&&(E=this.CHANGE_H_SCROLL),(a||p)&&(E=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal("scrollbarVisibilityChanged"),p&&(o=this.$getLongestLine())),this.layerConfig={width:o,padding:this.$padding,firstRow:w,firstRowScreen:m,lastRow:y,lineHeight:A,characterWidth:this.characterWidth,minHeight:h,maxHeight:r,offset:c,gutterOffset:Math.max(0,Math.ceil((c+t.height-t.scrollerHeight)/A)),height:this.$size.scrollerHeight},E},this.$updateLines=function(){var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var i=this.layerConfig;return e>i.lastRow+1||to?(t&&l+s>o+this.lineHeight&&(o-=t*this.$size.scrollerHeight),0===o&&(o=-this.scrollMargin.top),this.session.setScrollTop(o)):l+this.$size.scrollerHeight-ar?(ri;++i)r.push(o(i/this.STEPS,e,t-e));return r},this.scrollToLine=function(e,t,i,n){var r=this.$cursorLayer.getPixelPosition({row:e,column:0}),o=r.top;t&&(o-=this.$size.scrollerHeight/2);var s=this.scrollTop;this.session.setScrollTop(o),i!==!1&&this.animateScrolling(s,n)},this.animateScrolling=function(e,t){var i=this.scrollTop;if(this.$animatedScroll){var n=this;if(e!=i){if(this.$scrollAnimation){var r=this.$scrollAnimation.steps;if(r.length&&(e=r[0],e==i))return}var o=n.$calcSteps(e,i);this.$scrollAnimation={from:e,to:i,steps:o},clearInterval(this.$timer),n.session.setScrollTop(o.shift()),n.session.$scrollTop=i,this.$timer=setInterval(function(){o.length?(n.session.setScrollTop(o.shift()),n.session.$scrollTop=i):null!=i?(n.session.$scrollTop=-1,n.session.setScrollTop(i),i=null):(n.$timer=clearInterval(n.$timer),n.$scrollAnimation=null,t&&t())},10)}}},this.scrollToY=function(e){this.scrollTop!==e&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=e)},this.scrollToX=function(e){this.scrollLeft!==e&&(this.scrollLeft=e),this.$loop.schedule(this.CHANGE_H_SCROLL)},this.scrollTo=function(e,t){this.session.setScrollTop(t),this.session.setScrollLeft(t)},this.scrollBy=function(e,t){t&&this.session.setScrollTop(this.session.getScrollTop()+t),e&&this.session.setScrollLeft(this.session.getScrollLeft()+e)},this.isScrollableBy=function(e,t){return 0>t&&this.session.getScrollTop()>=1-this.scrollMargin.top?!0:t>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom?!0:0>e&&this.session.getScrollLeft()>=1-this.scrollMargin.left?!0:e>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right?!0:void 0},this.pixelToScreenCoordinates=function(e,t){var i=this.scroller.getBoundingClientRect(),n=(e+this.scrollLeft-i.left-this.$padding)/this.characterWidth,r=Math.floor((t+this.scrollTop-i.top)/this.lineHeight),o=Math.round(n);return{row:r,column:o,side:n-o>0?1:-1}},this.screenToTextCoordinates=function(e,t){var i=this.scroller.getBoundingClientRect(),n=Math.round((e+this.scrollLeft-i.left-this.$padding)/this.characterWidth),r=(t+this.scrollTop-i.top)/this.lineHeight;return this.session.screenToDocumentPosition(r,Math.max(n,0))},this.textToScreenCoordinates=function(e,t){var i=this.scroller.getBoundingClientRect(),n=this.session.documentToScreenPosition(e,t),r=this.$padding+Math.round(n.column*this.characterWidth),o=n.row*this.lineHeight;return{pageX:i.left+r-this.scrollLeft,pageY:i.top+o-this.scrollTop}},this.visualizeFocus=function(){r.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){r.removeCssClass(this.container,"ace_focus")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,r.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){this.$composition&&(r.removeCssClass(this.textarea,"ace_composition"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null)},this.setTheme=function(e,t){function i(i){if(n.$themeId!=e)return t&&t();if(i.cssClass){r.importCssString(i.cssText,i.cssClass,n.container.ownerDocument),n.theme&&r.removeCssClass(n.container,n.theme.cssClass);var o="padding"in i?i.padding:"padding"in(n.theme||{})?4:n.$padding;n.$padding&&o!=n.$padding&&n.setPadding(o),n.$theme=i.cssClass,n.theme=i,r.addCssClass(n.container,i.cssClass),r.setCssClass(n.container,"ace_dark",i.isDark),n.$size&&(n.$size.width=0,n.$updateSizeAsync()),n._dispatchEvent("themeLoaded",{theme:i}),t&&t()}}var n=this;if(this.$themeId=e,n._dispatchEvent("themeChange",{theme:e}),e&&"string"!=typeof e)i(e);else{var s=e||this.$options.theme.initialValue;o.loadModule(["theme",s],i)}},this.getTheme=function(){return this.$themeId},this.setStyle=function(e,t){r.setCssClass(this.container,e,t!==!1)},this.unsetStyle=function(e){r.removeCssClass(this.container,e)},this.setCursorStyle=function(e){this.scroller.style.cursor!=e&&(this.scroller.style.cursor=e)},this.setMouseCursor=function(e){this.scroller.style.cursor=e},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(v.prototype),o.defineOptions(v.prototype,"renderer",{animatedScroll:{initialValue:!1},showInvisibles:{set:function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!1},showPrintMargin:{set:function(){this.$updatePrintMargin()},initialValue:!0},printMarginColumn:{set:function(){this.$updatePrintMargin()},initialValue:80},printMargin:{set:function(e){"number"==typeof e&&(this.$printMarginColumn=e),this.$showPrintMargin=!!e,this.$updatePrintMargin()},get:function(){return this.$showPrintMargin&&this.$printMarginColumn}},showGutter:{set:function(e){this.$gutter.style.display=e?"block":"none",this.$loop.schedule(this.CHANGE_FULL),this.onGutterResize()},initialValue:!0},fadeFoldWidgets:{set:function(e){r.setCssClass(this.$gutter,"ace_fade-fold-widgets",e)},initialValue:!1},showFoldWidgets:{set:function(e){this.$gutterLayer.setShowFoldWidgets(e)},initialValue:!0},showLineNumbers:{set:function(e){this.$gutterLayer.setShowLineNumbers(e),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},displayIndentGuides:{set:function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!0},highlightGutterLine:{set:function(e){return this.$gutterLineHighlight?(this.$gutterLineHighlight.style.display=e?"":"none",void(this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight())):(this.$gutterLineHighlight=r.createElement("div"),this.$gutterLineHighlight.className="ace_gutter-active-line",void this.$gutter.appendChild(this.$gutterLineHighlight))},initialValue:!1,value:!0},hScrollBarAlwaysVisible:{set:function(e){this.$hScrollBarAlwaysVisible&&this.$horizScroll||this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},vScrollBarAlwaysVisible:{set:function(e){this.$vScrollBarAlwaysVisible&&this.$vScroll||this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},fontSize:{set:function(e){"number"==typeof e&&(e+="px"),this.container.style.fontSize=e,this.updateFontSize()},initialValue:12},fontFamily:{set:function(e){this.container.style.fontFamily=e,this.updateFontSize()}},maxLines:{set:function(e){this.updateFull()}},minLines:{set:function(e){this.updateFull()}},scrollPastEnd:{set:function(e){e=+e||0,this.$scrollPastEnd!=e&&(this.$scrollPastEnd=e,this.$loop.schedule(this.CHANGE_SCROLL))},initialValue:0,handlesSet:!0},fixedWidthGutter:{set:function(e){this.$gutterLayer.$fixedWidth=!!e,this.$loop.schedule(this.CHANGE_GUTTER)}},theme:{set:function(e){this.setTheme(e)},get:function(){return this.$themeId||this.theme},initialValue:"./theme/textmate",handlesSet:!0}}),t.VirtualRenderer=v}),ace.define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"],function(e,t,n){"use strict";var r=e("../lib/oop"),o=e("../lib/net"),s=e("../lib/event_emitter").EventEmitter,a=e("../config"),l=function(t,n,r,o){if(this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl),a.get("packaged")||!e.toUrl)o=o||a.moduleUrl(n.id,"worker");else{var s=this.$normalizePath;o=o||s(e.toUrl("ace/worker/worker.js",null,"_"));var l={};t.forEach(function(t){l[t]=s(e.toUrl(t,null,"_").replace(/(\.js)?(\?.*)?$/,""))})}try{var c=n.src,h=i(66),d=new h([c],{type:"application/javascript"}),u=(window.URL||window.webkitURL).createObjectURL(d);this.$worker=new Worker(u)}catch(f){if(!(f instanceof window.DOMException))throw f;var d=this.$workerBlob(o),p=window.URL||window.webkitURL,m=p.createObjectURL(d);this.$worker=new Worker(m),p.revokeObjectURL(m)}this.$worker.postMessage({init:!0,tlns:l,module:n.id,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onmessage=this.onMessage};(function(){r.implement(this,s),this.onMessage=function(e){var t=e.data;switch(t.type){case"event":this._signal(t.name,{data:t.data});break;case"call":var i=this.callbacks[t.id];i&&(i(t.data),delete this.callbacks[t.id]);break;case"error":this.reportError(t.data);break;case"log":window.console&&console.log&&console.log.apply(console,t.data)}},this.reportError=function(e){window.console&&console.error&&console.error(e)},this.$normalizePath=function(e){return o.qualifyURL(e)},this.terminate=function(){this._signal("terminate",{}),this.deltaQueue=null,this.$worker.terminate(),this.$worker=null,this.$doc&&this.$doc.off("change",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,i){if(i){var n=this.callbackId++;this.callbacks[n]=i,t.push(n)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(i){console.error(i.stack)}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call("setValue",[e.getValue()]),e.on("change",this.changeListener)},this.changeListener=function(e){this.deltaQueue||(this.deltaQueue=[],setTimeout(this.$sendDeltaQueue,0)),"insert"==e.action?this.deltaQueue.push(e.start,e.lines):this.deltaQueue.push(e.start,e.end)},this.$sendDeltaQueue=function(){var e=this.deltaQueue;e&&(this.deltaQueue=null,e.length>50&&e.length>this.$doc.getLength()>>1?this.call("setValue",[this.$doc.getValue()]):this.emit("change",{data:e}))},this.$workerBlob=function(e){var t="importScripts('"+o.qualifyURL(e)+"');";try{return new Blob([t],{type:"application/javascript"})}catch(i){var n=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder,r=new n;return r.append(t),r.getBlob("application/javascript")}}}).call(l.prototype);var c=function(e,t,i){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var n=null,r=!1,o=Object.create(s),l=this;this.$worker={},this.$worker.terminate=function(){},this.$worker.postMessage=function(e){l.messageBuffer.push(e),n&&(r?setTimeout(c):c())},this.setEmitSync=function(e){r=e};var c=function(){var e=l.messageBuffer.shift();e.command?n[e.command].apply(n,e.args):e.event&&o._signal(e.event,e.data)};o.postMessage=function(e){l.onMessage({data:e})},o.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},o.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},a.loadModule(["worker",t],function(e){for(n=new e[i](o);l.messageBuffer.length;)c()})};c.prototype=l.prototype,t.UIWorkerClient=c,t.WorkerClient=l}),ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,t,i){"use strict";var n=e("./range").Range,r=e("./lib/event_emitter").EventEmitter,o=e("./lib/oop"),s=function(e,t,i,n,r,o){var s=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=r,this.othersClass=o,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=n,this.$onCursorChange=function(){setTimeout(function(){s.onCursorChange()})},this.$pos=i;var a=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=a.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){o.implement(this,r),this.setup=function(){var e=this,t=this.doc,i=this.session;this.selectionBefore=i.selection.toJSON(),i.selection.inMultiSelectMode&&i.selection.toSingleRange(),this.pos=t.createAnchor(this.$pos.row,this.$pos.column);var r=this.pos;r.$insertRight=!0,r.detach(),r.markerId=i.addMarker(new n(r.row,r.column,r.row,r.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(i){var n=t.createAnchor(i.row,i.column);n.$insertRight=!0,n.detach(),e.others.push(n)}),i.setUndoSelect(!1)},this.showOtherMarkers=function(){if(!this.othersActive){var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(i){i.markerId=e.addMarker(new n(i.row,i.column,i.row,i.column+t.length),t.othersClass,null,!1)})}},this.hideOtherMarkers=function(){if(this.othersActive){this.othersActive=!1;for(var e=0;e=this.pos.column&&t.start.column<=this.pos.column+this.length+1,o=t.start.column-this.pos.column;if(this.updateAnchors(e),r&&(this.length+=i),r&&!this.session.$fromUndo)if("insert"===e.action)for(var s=this.others.length-1;s>=0;s--){var a=this.others[s],l={row:a.row,column:a.column+o};this.doc.insertMergedLines(l,e.lines)}else if("remove"===e.action)for(var s=this.others.length-1;s>=0;s--){var a=this.others[s],l={row:a.row,column:a.column+o};this.doc.remove(new n(l.row,l.column,l.row,l.column-i))}this.$updating=!1,this.updateMarkers()}},this.updateAnchors=function(e){this.pos.onChange(e);for(var t=this.others.length;t--;)this.others[t].onChange(e);this.updateMarkers()},this.updateMarkers=function(){if(!this.$updating){var e=this,t=this.session,i=function(i,r){t.removeMarker(i.markerId),i.markerId=t.addMarker(new n(i.row,i.column,i.row,i.column+e.length),r,null,!1)};i(this.pos,this.mainClass);for(var r=this.others.length;r--;)i(this.others[r],this.othersClass)}},this.onCursorChange=function(e){if(!this.$updating&&this.session){var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e))}},this.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},this.cancel=function(){if(-1!==this.$undoStackDepth){for(var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth,i=0;t>i;i++)e.undo(!0);this.selectionBefore&&this.session.selection.fromJSON(this.selectionBefore)}}}).call(s.prototype),t.PlaceHolder=s}),ace.define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,t,i){function n(e,t){return e.row==t.row&&e.column==t.column}function r(e){var t=e.domEvent,i=t.altKey,r=t.shiftKey,a=t.ctrlKey,l=e.getAccelKey(),c=e.getButton();if(a&&s.isMac&&(c=t.button),e.editor.inMultiSelectMode&&2==c)return void e.editor.textInput.onContextMenu(e.domEvent);if(!a&&!i&&!l)return void(0===c&&e.editor.inMultiSelectMode&&e.editor.exitMultiSelectMode());if(0===c){var h,d=e.editor,u=d.selection,f=d.inMultiSelectMode,p=e.getDocumentPosition(),m=u.getCursor(),g=e.inSelection()||u.isEmpty()&&n(p,m),v=e.x,w=e.y,y=function(e){v=e.clientX,w=e.clientY},A=d.session,C=d.renderer.pixelToScreenCoordinates(v,w),E=C;if(d.$mouseHandler.$enableJumpToDef)a&&i||l&&i?h=r?"block":"add":i&&d.$blockSelectEnabled&&(h="block");else if(l&&!i){if(h="add",!f&&r)return}else i&&d.$blockSelectEnabled&&(h="block");if(h&&s.isMac&&t.ctrlKey&&d.$mouseHandler.cancelContextMenu(),"add"==h){if(!f&&g)return;if(!f){var b=u.toOrientedRange();d.addSelectionMarker(b)}var F=u.rangeList.rangeAtPoint(p);d.$blockScrolling++,d.inVirtualSelectionMode=!0,r&&(F=null,b=u.ranges[0]||b,d.removeSelectionMarker(b)),d.once("mouseup",function(){var e=u.toOrientedRange();F&&e.isEmpty()&&n(F.cursor,e.cursor)?u.substractPoint(e.cursor):(r?u.substractPoint(b.cursor):b&&(d.removeSelectionMarker(b),u.addRange(b)),u.addRange(e)),d.$blockScrolling--,d.inVirtualSelectionMode=!1})}else if("block"==h){e.stop(),d.inVirtualSelectionMode=!0;var x,S=[],$=function(){var e=d.renderer.pixelToScreenCoordinates(v,w),t=A.screenToDocumentPosition(e.row,e.column);n(E,e)&&n(t,u.lead)||(E=e,d.$blockScrolling++,d.selection.moveToPosition(t),d.renderer.scrollCursorIntoView(),d.removeSelectionMarkers(S),S=u.rectangularRangeBlock(E,C),d.$mouseHandler.$clickSelection&&1==S.length&&S[0].isEmpty()&&(S[0]=d.$mouseHandler.$clickSelection.clone()),S.forEach(d.addSelectionMarker,d),d.updateSelectionMarkers(),d.$blockScrolling--)};d.$blockScrolling++,f&&!l?u.toSingleRange():!f&&l&&(x=u.toOrientedRange(),d.addSelectionMarker(x)),r?C=A.documentToScreenPosition(u.lead):u.moveToPosition(p),d.$blockScrolling--,E={row:-1,column:-1};var D=function(e){clearInterval(B),d.removeSelectionMarkers(S),S.length||(S=[u.toOrientedRange()]),d.$blockScrolling++,x&&(d.removeSelectionMarker(x),u.toSingleRange(x));for(var t=0;t1&&!this.inMultiSelectMode&&(this._signal("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)}},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);return t?(this.$onRemoveRange(t),t[0]):void 0},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._signal("addRange",{range:e})},this.$onRemoveRange=function(e){if(this.rangeCount=this.rangeList.ranges.length,1==this.rangeCount&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var i=e.length;i--;){var n=this.ranges.indexOf(e[i]);this.ranges.splice(n,1)}this._signal("removeRange",{ranges:e}),0===this.rangeCount&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){this.rangeList||(this.rangeList=new a,this.ranges=[],this.rangeCount=0)},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],i=l.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(i,t.cursor==t.start)}else{var i=this.getRange(),n=this.isBackwards(),r=i.start.row,o=i.end.row;if(r==o){if(n)var s=i.end,a=i.start;else var s=i.start,a=i.end;return this.addRange(l.fromPoints(a,a)),void this.addRange(l.fromPoints(s,s))}var c=[],h=this.getLineRange(r,!0);h.start.column=i.start.column,c.push(h);for(var d=r+1;o>d;d++)c.push(this.getLineRange(d,!0));h=this.getLineRange(o,!0),h.end.column=i.end.column,c.push(h),c.forEach(this.addRange,this)}},this.toggleBlockSelection=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],i=l.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(i,t.cursor==t.start)}else{var n=this.session.documentToScreenPosition(this.selectionLead),r=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(n,r);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,i){var n=[],o=e.columns&&(s=0),0>h&&(h=0),h==d&&(i=!0);for(var u=h;d>=u;u++){var f=l.fromPoints(this.session.screenToDocumentPosition(u,s),this.session.screenToDocumentPosition(u,a));if(f.isEmpty()){if(p&&r(f.end,p))break;var p=f.end}f.cursor=o?f.start:f.end,n.push(f)}if(c&&n.reverse(),!i){for(var m=n.length-1;n[m].isEmpty()&&m>0;)m--;if(m>0)for(var g=0;n[g].isEmpty();)g++;for(var v=m;v>=g;v--)n[v].isEmpty()&&n.splice(v,1)}return n}}.call(c.prototype);var v=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,"ace_selection",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(e.marker){this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);-1!=t&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length}},this.removeSelectionMarkers=function(e){for(var t=this.session.$selectionMarkers,i=e.length;i--;){var n=e[i];if(n.marker){this.session.removeMarker(n.marker);var r=t.indexOf(n);-1!=r&&t.splice(r,1)}}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){this.inMultiSelectMode||(this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.setDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers())},this.$onSingleSelect=function(e){this.session.multiSelect.inVirtualMode||(this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit("changeSelection"))},this.$onMultiSelectExec=function(e){var t=e.command,i=e.editor;if(i.multiSelect){if(t.multiSelectAction)"forEach"==t.multiSelectAction?n=i.forEachSelection(t,e.args):"forEachLine"==t.multiSelectAction?n=i.forEachSelection(t,e.args,!0):"single"==t.multiSelectAction?(i.exitMultiSelectMode(),n=t.exec(i,e.args||{})):n=t.multiSelectAction(i,e.args||{});else{var n=t.exec(i,e.args||{});i.multiSelect.addRange(i.multiSelect.toOrientedRange()),i.multiSelect.mergeOverlappingRanges()}return n}},this.forEachSelection=function(e,t,i){if(!this.inVirtualSelectionMode){var n,r=i&&i.keepOrder,o=1==i||i&&i.$byLines,s=this.session,a=this.selection,l=a.rangeList,h=(r?a:l).ranges;if(!h.length)return e.exec?e.exec(this,t||{}):e(this,t||{});var d=a._eventRegistry;a._eventRegistry={};var u=new c(s);this.inVirtualSelectionMode=!0;for(var f=h.length;f--;){if(o)for(;f>0&&h[f].start.row==h[f-1].end.row;)f--;u.fromOrientedRange(h[f]),u.index=f,this.selection=s.selection=u;var p=e.exec?e.exec(this,t||{}):e(this,t||{});n||void 0===p||(n=p),u.toOrientedRange(h[f])}u.detach(),this.selection=s.selection=a,this.inVirtualSelectionMode=!1,a._eventRegistry=d,a.mergeOverlappingRanges();var m=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),m&&m.from==m.to&&this.renderer.animateScrolling(m.from),n}},this.exitMultiSelectMode=function(){this.inMultiSelectMode&&!this.inVirtualSelectionMode&&this.multiSelect.toSingleRange()},this.getSelectedText=function(){var e="";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){for(var t=this.multiSelect.rangeList.ranges,i=[],n=0;ne?a.unshift(a.pop()):a.push(a.shift());for(var r=n.length;r--;){var o=n[r],s=o.clone();t.replace(o,a[r]),o.start.row=s.start.row,o.start.column=s.start.column}},this.selectMore=function(e,t,i){var r=this.session,o=r.multiSelect,s=o.toOrientedRange();if(!s.isEmpty()||(s=r.getWordRange(s.start.row,s.start.column),s.cursor=-1==e?s.start:s.end,this.multiSelect.addRange(s),!i)){var a=r.getTextRange(s),l=n(r,a,e);l&&(l.cursor=-1==e?l.start:l.end,this.$blockScrolling+=1,this.session.unfold(l),this.multiSelect.addRange(l),this.$blockScrolling-=1,this.renderer.scrollCursorIntoView(null,.5)),t&&this.multiSelect.substractPoint(s.cursor)}},this.alignCursors=function(){var e=this.session,t=e.multiSelect,i=t.ranges,n=-1,r=i.filter(function(e){return e.cursor.row==n?!0:void(n=e.cursor.row)});if(i.length&&r.length!=i.length-1){r.forEach(function(e){t.substractPoint(e.cursor)});var o=0,s=1/0,a=i.map(function(t){var i=t.cursor,n=e.getLine(i.row),r=n.substr(i.column).search(/\S/g);return-1==r&&(r=0),i.column>o&&(o=i.column),s>r&&(s=r),r});i.forEach(function(t,i){var n=t.cursor,r=o-n.column,c=a[i]-s;r>c?e.insert(n,u.stringRepeat(" ",r-c)):e.remove(new l(n.row,n.column,n.row,n.column-r+c)),t.start.column=t.end.column=o,t.start.row=t.end.row=n.row,t.cursor=t.end}),t.fromOrientedRange(i[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}else{var c=this.selection.getRange(),h=c.start.row,d=c.end.row,f=h==d;if(f){var p,m=this.session.getLength();do p=this.session.getLine(d);while(/[=:]/.test(p)&&++d0);0>h&&(h=0),d>=m&&(d=m-1)}var g=this.session.removeFullLines(h,d);g=this.$reAlignText(g,f),this.session.insert({row:h,column:0},g.join("\n")+"\n"),f||(c.start.column=0,c.end.column=g[g.length-1].length),this.selection.setRange(c)}},this.$reAlignText=function(e,t){function i(e){return u.stringRepeat(" ",e)}function n(e){return e[2]?i(s)+e[2]+i(a-e[2].length+l)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function r(e){return e[2]?i(s+a-e[2].length)+e[2]+i(l," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function o(e){return e[2]?i(s)+e[2]+i(l)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}var s,a,l,c=!0,h=!0;return e.map(function(e){var t=e.match(/(\s*)(.*?)(\s*)([=:].*)/);return t?null==s?(s=t[1].length,a=t[2].length,l=t[3].length,t):(s+a+l!=t[1].length+t[2].length+t[3].length&&(h=!1),s!=t[1].length&&(c=!1),s>t[1].length&&(s=t[1].length),at[3].length&&(l=t[3].length),t):[e]}).map(t?n:c?h?r:n:o)}}).call(v.prototype),t.onSessionChange=function(e){var t=e.session;t&&!t.multiSelect&&(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t&&t.multiSelect;var i=e.oldSession;i&&(i.multiSelect.off("addRange",this.$onAddRange),i.multiSelect.off("removeRange",this.$onRemoveRange),i.multiSelect.off("multiSelect",this.$onMultiSelect),i.multiSelect.off("singleSelect",this.$onSingleSelect),i.multiSelect.lead.off("change",this.$checkMultiselectChange),i.multiSelect.anchor.off("change",this.$checkMultiselectChange)),t&&(t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),t.multiSelect.lead.on("change",this.$checkMultiselectChange),t.multiSelect.anchor.on("change",this.$checkMultiselectChange)),t&&this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=o,e("./config").defineOptions(v.prototype,"editor",{enableMultiselect:{set:function(e){o(this),e?(this.on("changeSession",this.$multiselectOnSessionChange),this.on("mousedown",h)):(this.off("changeSession",this.$multiselectOnSessionChange),this.off("mousedown",h))},value:!0},enableBlockSelect:{set:function(e){this.$blockSelectEnabled=e},value:!0}})}),ace.define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(e,t,i){"use strict";var n=e("../../range").Range,r=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,i){var n=e.getLine(i);return this.foldingStartMarker.test(n)?"start":"markbeginend"==t&&this.foldingStopMarker&&this.foldingStopMarker.test(n)?"end":""},this.getFoldWidgetRange=function(e,t,i){return null},this.indentationBlock=function(e,t,i){var r=/\S/,o=e.getLine(t),s=o.search(r);if(-1!=s){for(var a=i||o.length,l=e.getLength(),c=t,h=t;++t=d)break;h=t}}if(h>c){var u=e.getLine(h).length;return new n(c,a,h,u)}}},this.openingBracketBlock=function(e,t,i,r,o){var s={row:i,column:r+1},a=e.$findClosingBracket(t,s,o);if(a){var l=e.foldWidgets[a.row];return null==l&&(l=e.getFoldWidget(a.row)),"start"==l&&a.row>s.row&&(a.row--,a.column=e.getLine(a.row).length),n.fromPoints(s,a)}},this.closingBracketBlock=function(e,t,i,r,o){var s={row:i,column:r},a=e.$findOpeningBracket(t,s);return a?(a.column++,s.column--,n.fromPoints(a,s)):void 0}}).call(r.prototype)}),ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,i){"use strict";t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter { background: #f0f0f0; color: #333; } .ace-tm .ace_print-margin { width: 1px; background: #e8e8e8; } .ace-tm .ace_fold { background-color: #6B72E6; } .ace-tm { background-color: #FFFFFF; color: black; } .ace-tm .ace_cursor { color: black; } .ace-tm .ace_invisible { color: rgb(191, 191, 191); } .ace-tm .ace_storage, .ace-tm .ace_keyword { color: blue; } .ace-tm .ace_constant { color: rgb(197, 6, 11); } .ace-tm .ace_constant.ace_buildin { color: rgb(88, 72, 246); } .ace-tm .ace_constant.ace_language { color: rgb(88, 92, 246); } .ace-tm .ace_constant.ace_library { color: rgb(6, 150, 14); } .ace-tm .ace_invalid { background-color: rgba(255, 0, 0, 0.1); color: red; } .ace-tm .ace_support.ace_function { color: rgb(60, 76, 114); } .ace-tm .ace_support.ace_constant { color: rgb(6, 150, 14); } .ace-tm .ace_support.ace_type, .ace-tm .ace_support.ace_class { color: rgb(109, 121, 222); } .ace-tm .ace_keyword.ace_operator { color: rgb(104, 118, 135); } .ace-tm .ace_string { color: rgb(3, 106, 7); } .ace-tm .ace_comment { color: rgb(76, 136, 107); } .ace-tm .ace_comment.ace_doc { color: rgb(0, 102, 255); } .ace-tm .ace_comment.ace_doc.ace_tag { color: rgb(128, 159, 191); } .ace-tm .ace_constant.ace_numeric { color: rgb(0, 0, 205); } .ace-tm .ace_variable { color: rgb(49, 132, 149); } .ace-tm .ace_xml-pe { color: rgb(104, 104, 91); } .ace-tm .ace_entity.ace_name.ace_function { color: #0000A2; } .ace-tm .ace_heading { color: rgb(12, 7, 255); } .ace-tm .ace_list { color:rgb(185, 6, 144); } .ace-tm .ace_meta.ace_tag { color:rgb(0, 22, 142); } .ace-tm .ace_string.ace_regex { color: rgb(255, 0, 0) } .ace-tm .ace_marker-layer .ace_selection { background: rgb(181, 213, 255); } .ace-tm.ace_multiselect .ace_selection.ace_start { box-shadow: 0 0 3px 0px white; } .ace-tm .ace_marker-layer .ace_step { background: rgb(252, 255, 0); } .ace-tm .ace_marker-layer .ace_stack { background: rgb(164, 229, 101); } .ace-tm .ace_marker-layer .ace_bracket { margin: -1px 0 0 -1px; border: 1px solid rgb(192, 192, 192); } .ace-tm .ace_marker-layer .ace_active-line { background: rgba(0, 0, 0, 0.07); } .ace-tm .ace_gutter-active-line { background-color : #dcdcdc; } .ace-tm .ace_marker-layer .ace_selected-word { background: rgb(250, 250, 255); border: 1px solid rgb(200, 200, 250); } .ace-tm .ace_indent-guide { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y; } ';var n=e("../lib/dom");n.importCssString(t.cssText,t.cssClass)}),ace.define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"],function(e,t,i){"use strict";function n(e){this.session=e,this.session.widgetManager=this,this.session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.$onChangeEditor=this.$onChangeEditor.bind(this),this.session.on("change",this.updateOnChange),this.session.on("changeFold",this.updateOnFold),this.session.on("changeEditor",this.$onChangeEditor)}var r=(e("./lib/oop"),e("./lib/dom"));e("./range").Range;(function(){this.getRowLength=function(e){var t;return t=this.lineWidgets?this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0:0,this.$useWrapMode&&this.$wrapData[e]?this.$wrapData[e].length+1+t:1+t},this.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&!t.hidden&&(e+=t.rowCount)}),e},this.$onChangeEditor=function(e){this.attach(e.editor)},this.attach=function(e){e&&e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach(),this.editor!=e&&(this.detach(),this.editor=e,e&&(e.widgetManager=this,e.renderer.on("beforeRender",this.measureWidgets),e.renderer.on("afterRender",this.renderWidgets)))},this.detach=function(e){var t=this.editor;if(t){this.editor=null,t.widgetManager=null,t.renderer.off("beforeRender",this.measureWidgets),t.renderer.off("afterRender",this.renderWidgets);var i=this.session.lineWidgets;i&&i.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))})}},this.updateOnFold=function(e,t){var i=t.lineWidgets;if(i&&e.action){for(var n=e.data,r=n.start.row,o=n.end.row,s="add"==e.action,a=r+1;o>a;a++)i[a]&&(i[a].hidden=s);i[o]&&(s?i[r]?i[o].hidden=s:i[r]=i[o]:(i[r]==i[o]&&(i[r]=void 0),i[o].hidden=s))}},this.updateOnChange=function(e){var t=this.session.lineWidgets;if(t){var i=e.start.row,n=e.end.row-i;if(0===n);else if("remove"==e.action){var r=t.splice(i+1,n);r.forEach(function(e){e&&this.removeLineWidget(e)},this),this.$updateRows()}else{var o=new Array(n);o.unshift(i,0),t.splice.apply(t,o),this.$updateRows()}}},this.$updateRows=function(){var e=this.session.lineWidgets;if(e){var t=!0;e.forEach(function(e,i){if(e)for(t=!1,e.row=i;e.$oldWidget;)e.$oldWidget.row=i,e=e.$oldWidget}),t&&(this.session.lineWidgets=null)}},this.addLineWidget=function(e){this.session.lineWidgets||(this.session.lineWidgets=new Array(this.session.getLength()));var t=this.session.lineWidgets[e.row];t&&(e.$oldWidget=t,t.el&&t.el.parentNode&&(t.el.parentNode.removeChild(t.el),t._inDocument=!1)),this.session.lineWidgets[e.row]=e,e.session=this.session;var i=this.editor.renderer;e.html&&!e.el&&(e.el=r.createElement("div"),e.el.innerHTML=e.html),e.el&&(r.addCssClass(e.el,"ace_lineWidgetContainer"),e.el.style.position="absolute",e.el.style.zIndex=5,i.container.appendChild(e.el),e._inDocument=!0),e.coverGutter||(e.el.style.zIndex=3),e.pixelHeight||(e.pixelHeight=e.el.offsetHeight),null==e.rowCount&&(e.rowCount=e.pixelHeight/i.layerConfig.lineHeight);var n=this.session.getFoldAt(e.row,0);if(e.$fold=n,n){var o=this.session.lineWidgets;e.row!=n.end.row||o[n.start.row]?e.hidden=!0:o[n.start.row]=e}return this.session._emit("changeFold",{data:{start:{row:e.row}}}),this.$updateRows(),this.renderWidgets(null,i),this.onWidgetChanged(e),e},this.removeLineWidget=function(e){if(e._inDocument=!1,e.session=null,e.el&&e.el.parentNode&&e.el.parentNode.removeChild(e.el),e.editor&&e.editor.destroy)try{e.editor.destroy()}catch(t){}if(this.session.lineWidgets){var i=this.session.lineWidgets[e.row];if(i==e)this.session.lineWidgets[e.row]=e.$oldWidget,e.$oldWidget&&this.onWidgetChanged(e.$oldWidget);else for(;i;){if(i.$oldWidget==e){i.$oldWidget=e.$oldWidget;break}i=i.$oldWidget}}this.session._emit("changeFold",{data:{start:{row:e.row}}}),this.$updateRows()},this.getWidgetsAtRow=function(e){for(var t=this.session.lineWidgets,i=t&&t[e],n=[];i;)n.push(i),i=i.$oldWidget;return n},this.onWidgetChanged=function(e){this.session._changedWidgets.push(e),this.editor&&this.editor.renderer.updateFull()},this.measureWidgets=function(e,t){var i=this.session._changedWidgets,n=t.layerConfig;if(i&&i.length){for(var r=1/0,o=0;oa&&(a=0)),s.rowCount!=a&&(s.rowCount=a,s.row0&&!n[r];)r--;this.firstRow=i.firstRow,this.lastRow=i.lastRow,t.$cursorLayer.config=i;for(var s=r;o>=s;s++){var a=n[s];if(a&&a.el)if(a.hidden)a.el.style.top=-100-(a.pixelHeight||0)+"px";else{a._inDocument||(a._inDocument=!0,t.container.appendChild(a.el));var l=t.$cursorLayer.getPixelPosition({row:s,column:0},!0).top;a.coverLine||(l+=i.lineHeight*this.session.getRowLineCount(a.row)),a.el.style.top=l-i.offset+"px";var c=a.coverGutter?0:t.gutterWidth;a.fixedWidth||(c-=t.scrollLeft),a.el.style.left=c+"px",a.fullWidth&&a.screenWidth&&(a.el.style.minWidth=i.width+2*i.padding+"px"),a.fixedWidth?a.el.style.right=t.scrollBar.getWidth()+"px":a.el.style.right=""}}}}}).call(n.prototype),t.LineWidgets=n}),ace.define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"],function(e,t,i){"use strict";function n(e,t,i){for(var n=0,r=e.length-1;r>=n;){var o=n+r>>1,s=i(t,e[o]);if(s>0)n=o+1;else{if(!(0>s))return o;r=o-1}}return-(n+1)}function r(e,t,i){var r=e.getAnnotations().sort(a.comparePoints);if(r.length){var o=n(r,{row:t,column:-1},a.comparePoints);0>o&&(o=-o-1),o>=r.length?o=i>0?0:r.length-1:0===o&&0>i&&(o=r.length-1);var s=r[o];if(s&&i){if(s.row===t){do s=r[o+=i];while(s&&s.row===t);if(!s)return r.slice()}var l=[];t=s.row; +do l[0>i?"unshift":"push"](s),s=r[o+=i];while(s&&s.row==t);return l.length&&l}}}var o=e("../line_widgets").LineWidgets,s=e("../lib/dom"),a=e("../range").Range;t.showErrorMarker=function(e,t){var i=e.session;i.widgetManager||(i.widgetManager=new o(i),i.widgetManager.attach(e));var n=e.getCursorPosition(),a=n.row,l=i.widgetManager.getWidgetsAtRow(a).filter(function(e){return"errorMarker"==e.type})[0];l?l.destroy():a-=t;var c,h=r(i,a,t);if(h){var d=h[0];n.column=(d.pos&&"number"!=typeof d.column?d.pos.sc:d.column)||0,n.row=d.row,c=e.renderer.$gutterLayer.$annotations[n.row]}else{if(l)return;c={text:["Looks good!"],className:"ace_ok"}}e.session.unfold(n.row),e.selection.moveToPosition(n);var u={row:n.row,fixedWidth:!0,coverGutter:!0,el:s.createElement("div"),type:"errorMarker"},f=u.el.appendChild(s.createElement("div")),p=u.el.appendChild(s.createElement("div"));p.className="error_widget_arrow "+c.className;var m=e.renderer.$cursorLayer.getPixelPosition(n).left;p.style.left=m+e.renderer.gutterWidth-5+"px",u.el.className="error_widget_wrapper",f.className="error_widget "+c.className,f.innerHTML=c.text.join("
"),f.appendChild(s.createElement("div"));var g=function(e,t,i){return 0!==t||"esc"!==i&&"return"!==i?void 0:(u.destroy(),{command:"null"})};u.destroy=function(){e.$mouseHandler.isMousePressed||(e.keyBinding.removeKeyboardHandler(g),i.widgetManager.removeLineWidget(u),e.off("changeSelection",u.destroy),e.off("changeSession",u.destroy),e.off("mouseup",u.destroy),e.off("change",u.destroy))},e.keyBinding.addKeyboardHandler(g),e.on("changeSelection",u.destroy),e.on("changeSession",u.destroy),e.on("mouseup",u.destroy),e.on("change",u.destroy),e.session.widgetManager.addLineWidget(u),u.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:u.el.offsetHeight})},s.importCssString(" .error_widget_wrapper { background: inherit; color: inherit; border:none } .error_widget { border-top: solid 2px; border-bottom: solid 2px; margin: 5px 0; padding: 10px 40px; white-space: pre-wrap; } .error_widget.ace_error, .error_widget_arrow.ace_error{ border-color: #ff5a5a } .error_widget.ace_warning, .error_widget_arrow.ace_warning{ border-color: #F1D817 } .error_widget.ace_info, .error_widget_arrow.ace_info{ border-color: #5a5a5a } .error_widget.ace_ok, .error_widget_arrow.ace_ok{ border-color: #5aaa5a } .error_widget_arrow { position: absolute; border: solid 5px; border-top-color: transparent!important; border-right-color: transparent!important; border-left-color: transparent!important; top: -5px; } ","")}),ace.define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"],function(e,t,i){"use strict";e("./lib/fixoldbrowsers");var n=e("./lib/dom"),r=e("./lib/event"),o=e("./editor").Editor,s=e("./edit_session").EditSession,a=e("./undomanager").UndoManager,l=e("./virtual_renderer").VirtualRenderer;e("./worker/worker_client"),e("./keyboard/hash_handler"),e("./placeholder"),e("./multi_select"),e("./mode/folding/fold_mode"),e("./theme/textmate"),e("./ext/error_marker"),t.config=e("./config"),t.acequire=e,t.edit=function(e){if("string"==typeof e){var i=e;if(e=document.getElementById(i),!e)throw new Error("ace.edit can't find div #"+i)}if(e&&e.env&&e.env.editor instanceof o)return e.env.editor;var s="";if(e&&/input|textarea/i.test(e.tagName)){var a=e;s=a.value,e=n.createElement("pre"),a.parentNode.replaceChild(e,a)}else e&&(s=n.getInnerText(e),e.innerHTML="");var c=t.createEditSession(s),h=new o(new l(e));h.setSession(c);var d={document:c,editor:h,onResize:h.resize.bind(h,null)};return a&&(d.textarea=a),r.addListener(window,"resize",d.onResize),h.on("destroy",function(){r.removeListener(window,"resize",d.onResize),d.editor.container.env=null}),h.container.env=h.env=d,h},t.createEditSession=function(e,t){var i=new s(e,t);return i.setUndoManager(new a),i},t.EditSession=s,t.UndoManager=a,t.version="1.2.3"}),function(){ace.acequire(["ace/ace"],function(e){e&&e.config.init(!0),window.ace||(window.ace=e);for(var t in e)e.hasOwnProperty(t)&&(window.ace[t]=e[t])})}(),e.exports=window.ace.acequire("ace/ace")},function(e,t){e.exports=function(){throw new Error("define cannot be used indirect")}},function(e,t){(function(t){function i(){if(t.Blob)try{return new Blob(["asdf"],{type:"text/plain"}),Blob}catch(e){}var i=t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder;return function(e,t){var n=new i,r=t.endings,o=t.type;if(r)for(var s=0,a=e.length;a>s;++s)n.append(e[s],r);else for(var s=0,a=e.length;a>s;++s)n.append(e[s]);return o?n.getBlob(o):n.getBlob()}}e.exports=i()}).call(t,function(){return this}())},function(e,t,i){ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,i){"use strict";var n=e("../lib/oop"),r=e("./text_highlight_rules").TextHighlightRules,o=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"},{token:"string",regex:"",next:"start"}]}};n.inherits(o,r),t.JsonHighlightRules=o}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,i){"use strict";var n=e("../range").Range,r=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var i=e.getLine(t),r=i.match(/^(\s*\})/);if(!r)return 0;var o=r[1].length,s=e.findMatchingBracket({row:t,column:o});if(!s||s.row==t)return 0;var a=this.$getIndent(e.getLine(s.row));e.replace(new n(t,0,t,o-1),a)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(r.prototype),t.MatchingBraceOutdent=r}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,i){"use strict";var n,r=e("../../lib/oop"),o=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,a=e("../../lib/lang"),l=["text","paren.rparen","punctuation.operator"],c=["text","paren.rparen","punctuation.operator","comment"],h={},d=function(e){var t=-1;return e.multiSelect&&(t=e.selection.index,h.rangeCount!=e.multiSelect.rangeCount&&(h={rangeCount:e.multiSelect.rangeCount})),h[t]?n=h[t]:void(n=h[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""})},u=function(e,t,i,n){var r=e.end.row-e.start.row;return{text:i+t+n,selection:[0,e.start.column+1,r,e.end.column+(r?0:1)]}},f=function(){this.add("braces","insertion",function(e,t,i,r,o){var s=i.getCursorPosition(),l=r.doc.getLine(s.row);if("{"==o){d(i);var c=i.getSelectionRange(),h=r.doc.getTextRange(c);if(""!==h&&"{"!==h&&i.getWrapBehavioursEnabled())return u(c,h,"{","}");if(f.isSaneInsertion(i,r))return/[\]\}\)]/.test(l[s.column])||i.inMultiSelectMode?(f.recordAutoInsert(i,r,"}"),{text:"{}",selection:[1,1]}):(f.recordMaybeInsert(i,r,"{"),{text:"{",selection:[1,1]})}else if("}"==o){d(i);var p=l.substring(s.column,s.column+1);if("}"==p){var m=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(null!==m&&f.isAutoInsertedClosing(s,l,o))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if("\n"==o||"\r\n"==o){d(i);var g="";f.isMaybeInsertedClosing(s,l)&&(g=a.stringRepeat("}",n.maybeInsertedBrackets),f.clearMaybeInsertedClosing());var p=l.substring(s.column,s.column+1);if("}"===p){var v=r.findMatchingBracket({row:s.row,column:s.column+1},"}");if(!v)return null;var w=this.$getIndent(r.getLine(v.row))}else{if(!g)return void f.clearMaybeInsertedClosing();var w=this.$getIndent(l)}var y=w+r.getTabString();return{text:"\n"+y+"\n"+w+g,selection:[1,y.length,1,y.length]}}f.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,i,r,o){var s=r.doc.getTextRange(o);if(!o.isMultiLine()&&"{"==s){d(i);var a=r.doc.getLine(o.start.row),l=a.substring(o.end.column,o.end.column+1);if("}"==l)return o.end.column++,o;n.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,i,n,r){if("("==r){d(i);var o=i.getSelectionRange(),s=n.doc.getTextRange(o);if(""!==s&&i.getWrapBehavioursEnabled())return u(o,s,"(",")");if(f.isSaneInsertion(i,n))return f.recordAutoInsert(i,n,")"),{text:"()",selection:[1,1]}}else if(")"==r){d(i);var a=i.getCursorPosition(),l=n.doc.getLine(a.row),c=l.substring(a.column,a.column+1);if(")"==c){var h=n.$findOpeningBracket(")",{column:a.column+1,row:a.row});if(null!==h&&f.isAutoInsertedClosing(a,l,r))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,i,n,r){var o=n.doc.getTextRange(r);if(!r.isMultiLine()&&"("==o){d(i);var s=n.doc.getLine(r.start.row),a=s.substring(r.start.column+1,r.start.column+2);if(")"==a)return r.end.column++,r}}),this.add("brackets","insertion",function(e,t,i,n,r){if("["==r){d(i);var o=i.getSelectionRange(),s=n.doc.getTextRange(o);if(""!==s&&i.getWrapBehavioursEnabled())return u(o,s,"[","]");if(f.isSaneInsertion(i,n))return f.recordAutoInsert(i,n,"]"),{text:"[]",selection:[1,1]}}else if("]"==r){d(i);var a=i.getCursorPosition(),l=n.doc.getLine(a.row),c=l.substring(a.column,a.column+1);if("]"==c){var h=n.$findOpeningBracket("]",{column:a.column+1,row:a.row});if(null!==h&&f.isAutoInsertedClosing(a,l,r))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,i,n,r){var o=n.doc.getTextRange(r);if(!r.isMultiLine()&&"["==o){d(i);var s=n.doc.getLine(r.start.row),a=s.substring(r.start.column+1,r.start.column+2);if("]"==a)return r.end.column++,r}}),this.add("string_dquotes","insertion",function(e,t,i,n,r){if('"'==r||"'"==r){d(i);var o=r,s=i.getSelectionRange(),a=n.doc.getTextRange(s);if(""!==a&&"'"!==a&&'"'!=a&&i.getWrapBehavioursEnabled())return u(s,a,o,o);if(!a){var l=i.getCursorPosition(),c=n.doc.getLine(l.row),h=c.substring(l.column-1,l.column),f=c.substring(l.column,l.column+1),p=n.getTokenAt(l.row,l.column),m=n.getTokenAt(l.row,l.column+1);if("\\"==h&&p&&/escape/.test(p.type))return null;var g,v=p&&/string|escape/.test(p.type),w=!m||/string|escape/.test(m.type);if(f==o)g=v!==w;else{if(v&&!w)return null;if(v&&w)return null;var y=n.$mode.tokenRe;y.lastIndex=0;var A=y.test(h);y.lastIndex=0;var C=y.test(h);if(A||C)return null;if(f&&!/[\s;,.})\]\\]/.test(f))return null;g=!0}return{text:g?o+o:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,i,n,r){var o=n.doc.getTextRange(r);if(!r.isMultiLine()&&('"'==o||"'"==o)){d(i);var s=n.doc.getLine(r.start.row),a=s.substring(r.start.column+1,r.start.column+2);if(a==o)return r.end.column++,r}})};f.isSaneInsertion=function(e,t){var i=e.getCursorPosition(),n=new s(t,i.row,i.column);if(!this.$matchTokenType(n.getCurrentToken()||"text",l)){var r=new s(t,i.row,i.column+1);if(!this.$matchTokenType(r.getCurrentToken()||"text",l))return!1}return n.stepForward(),n.getCurrentTokenRow()!==i.row||this.$matchTokenType(n.getCurrentToken()||"text",c)},f.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},f.recordAutoInsert=function(e,t,i){var r=e.getCursorPosition(),o=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,o,n.autoInsertedLineEnd[0])||(n.autoInsertedBrackets=0),n.autoInsertedRow=r.row,n.autoInsertedLineEnd=i+o.substr(r.column),n.autoInsertedBrackets++},f.recordMaybeInsert=function(e,t,i){var r=e.getCursorPosition(),o=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,o)||(n.maybeInsertedBrackets=0),n.maybeInsertedRow=r.row,n.maybeInsertedLineStart=o.substr(0,r.column)+i,n.maybeInsertedLineEnd=o.substr(r.column),n.maybeInsertedBrackets++},f.isAutoInsertedClosing=function(e,t,i){return n.autoInsertedBrackets>0&&e.row===n.autoInsertedRow&&i===n.autoInsertedLineEnd[0]&&t.substr(e.column)===n.autoInsertedLineEnd},f.isMaybeInsertedClosing=function(e,t){return n.maybeInsertedBrackets>0&&e.row===n.maybeInsertedRow&&t.substr(e.column)===n.maybeInsertedLineEnd&&t.substr(0,e.column)==n.maybeInsertedLineStart},f.popAutoInsertedClosing=function(){n.autoInsertedLineEnd=n.autoInsertedLineEnd.substr(1),n.autoInsertedBrackets--},f.clearMaybeInsertedClosing=function(){n&&(n.maybeInsertedBrackets=0,n.maybeInsertedRow=-1)},r.inherits(f,o),t.CstyleBehaviour=f}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,i){"use strict";var n=e("../../lib/oop"),r=e("../../range").Range,o=e("./fold_mode").FoldMode,s=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};n.inherits(s,o),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,i){var n=e.getLine(i);if(this.singleLineBlockCommentRe.test(n)&&!this.startRegionRe.test(n)&&!this.tripleStarBlockCommentRe.test(n))return"";var r=this._getFoldWidgetBase(e,t,i);return!r&&this.startRegionRe.test(n)?"start":r},this.getFoldWidgetRange=function(e,t,i,n){var r=e.getLine(i);if(this.startRegionRe.test(r))return this.getCommentRegionBlock(e,r,i);var o=r.match(this.foldingStartMarker);if(o){var s=o.index;if(o[1])return this.openingBracketBlock(e,o[1],i,s);var a=e.getCommentFoldRange(i,s+o[0].length,1);return a&&!a.isMultiLine()&&(n?a=this.getSectionRange(e,i):"all"!=t&&(a=null)),a}if("markbegin"!==t){var o=r.match(this.foldingStopMarker);if(o){var s=o.index+o[0].length;return o[1]?this.closingBracketBlock(e,o[1],i,s):e.getCommentFoldRange(i,s,-1)}}},this.getSectionRange=function(e,t){var i=e.getLine(t),n=i.search(/\S/),o=t,s=i.length;t+=1;for(var a=t,l=e.getLength();++tc)break;var h=this.getFoldWidgetRange(e,"all",t);if(h){if(h.start.row<=o)break;if(h.isMultiLine())t=h.end.row;else if(n==c)break}a=t}}return new r(o,s,a,e.getLine(a).length)},this.getCommentRegionBlock=function(e,t,i){for(var n=t.search(/\s*$/),o=e.getLength(),s=i,a=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,l=1;++is?new r(s,n,h,t.length):void 0}}.call(s.prototype)}),ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,n){"use strict";var r=e("../lib/oop"),o=e("./text").Mode,s=e("./json_highlight_rules").JsonHighlightRules,a=e("./matching_brace_outdent").MatchingBraceOutdent,l=e("./behaviour/cstyle").CstyleBehaviour,c=e("./folding/cstyle").FoldMode,h=e("../worker/worker_client").WorkerClient,d=function(){this.HighlightRules=s,this.$outdent=new a,this.$behaviour=new l,this.foldingRules=new c};r.inherits(d,o),function(){this.getNextLineIndent=function(e,t,i){var n=this.$getIndent(t);if("start"==e){var r=t.match(/^.*[\{\(\[]\s*$/);r&&(n+=i)}return n},this.checkOutdent=function(e,t,i){return this.$outdent.checkOutdent(t,i)},this.autoOutdent=function(e,t,i){this.$outdent.autoOutdent(t,i)},this.createWorker=function(e){var t=new h(["ace"],i(68),"JsonWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/json"}.call(d.prototype),t.Mode=d})},function(e,t){e.exports.id="ace/mode/json_worker",e.exports.src='"no use strict";(function(window){function resolveModuleId(id,paths){for(var testPath=id,tail="";testPath;){var alias=paths[testPath];if("string"==typeof alias)return alias+tail;if(alias)return alias.location.replace(/\\/*$/,"/")+(tail||alias.main||alias.name);if(alias===!1)return"";var i=testPath.lastIndexOf("/");if(-1===i)break;tail=testPath.substr(i)+tail,testPath=testPath.slice(0,i)}return id}if(!(void 0!==window.window&&window.document||window.acequire&&window.define)){window.console||(window.console=function(){var msgs=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:msgs})},window.console.error=window.console.warn=window.console.log=window.console.trace=window.console),window.window=window,window.ace=window,window.onerror=function(message,file,line,col,err){postMessage({type:"error",data:{message:message,data:err.data,file:file,line:line,col:col,stack:err.stack}})},window.normalizeModule=function(parentId,moduleName){if(-1!==moduleName.indexOf("!")){var chunks=moduleName.split("!");return window.normalizeModule(parentId,chunks[0])+"!"+window.normalizeModule(parentId,chunks[1])}if("."==moduleName.charAt(0)){var base=parentId.split("/").slice(0,-1).join("/");for(moduleName=(base?base+"/":"")+moduleName;-1!==moduleName.indexOf(".")&&previous!=moduleName;){var previous=moduleName;moduleName=moduleName.replace(/^\\.\\//,"").replace(/\\/\\.\\//,"/").replace(/[^\\/]+\\/\\.\\.\\//,"")}}return moduleName},window.acequire=function acequire(parentId,id){if(id||(id=parentId,parentId=null),!id.charAt)throw Error("worker.js acequire() accepts only (parentId, id) as arguments");id=window.normalizeModule(parentId,id);var module=window.acequire.modules[id];if(module)return module.initialized||(module.initialized=!0,module.exports=module.factory().exports),module.exports;if(!window.acequire.tlns)return console.log("unable to load "+id);var path=resolveModuleId(id,window.acequire.tlns);return".js"!=path.slice(-3)&&(path+=".js"),window.acequire.id=id,window.acequire.modules[id]={},importScripts(path),window.acequire(parentId,id)},window.acequire.modules={},window.acequire.tlns={},window.define=function(id,deps,factory){if(2==arguments.length?(factory=deps,"string"!=typeof id&&(deps=id,id=window.acequire.id)):1==arguments.length&&(factory=id,deps=[],id=window.acequire.id),"function"!=typeof factory)return window.acequire.modules[id]={exports:factory,initialized:!0},void 0;deps.length||(deps=["require","exports","module"]);var req=function(childId){return window.acequire(id,childId)};window.acequire.modules[id]={exports:{},factory:function(){var module=this,returnExports=factory.apply(this,deps.map(function(dep){switch(dep){case"require":return req;case"exports":return module.exports;case"module":return module;default:return req(dep)}}));return returnExports&&(module.exports=returnExports),module}}},window.define.amd={},acequire.tlns={},window.initBaseUrls=function(topLevelNamespaces){for(var i in topLevelNamespaces)acequire.tlns[i]=topLevelNamespaces[i]},window.initSender=function(){var EventEmitter=window.acequire("ace/lib/event_emitter").EventEmitter,oop=window.acequire("ace/lib/oop"),Sender=function(){};return function(){oop.implement(this,EventEmitter),this.callback=function(data,callbackId){postMessage({type:"call",id:callbackId,data:data})},this.emit=function(name,data){postMessage({type:"event",name:name,data:data})}}.call(Sender.prototype),new Sender};var main=window.main=null,sender=window.sender=null;window.onmessage=function(e){var msg=e.data;if(msg.event&&sender)sender._signal(msg.event,msg.data);else if(msg.command)if(main[msg.command])main[msg.command].apply(main,msg.args);else{if(!window[msg.command])throw Error("Unknown command:"+msg.command);window[msg.command].apply(window,msg.args)}else if(msg.init){window.initBaseUrls(msg.tlns),acequire("ace/lib/es5-shim"),sender=window.sender=window.initSender();var clazz=acequire(msg.module)[msg.classname];main=window.main=new clazz(sender)}}}})(this),ace.define("ace/lib/oop",["require","exports","module"],function(acequire,exports){"use strict";exports.inherits=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})},exports.mixin=function(obj,mixin){for(var key in mixin)obj[key]=mixin[key];return obj},exports.implement=function(proto,mixin){exports.mixin(proto,mixin)}}),ace.define("ace/range",["require","exports","module"],function(acequire,exports){"use strict";var comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},Range=function(startRow,startColumn,endRow,endColumn){this.start={row:startRow,column:startColumn},this.end={row:endRow,column:endColumn}};(function(){this.isEqual=function(range){return this.start.row===range.start.row&&this.end.row===range.end.row&&this.start.column===range.start.column&&this.end.column===range.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(row,column){return 0==this.compare(row,column)},this.compareRange=function(range){var cmp,end=range.end,start=range.start;return cmp=this.compare(end.row,end.column),1==cmp?(cmp=this.compare(start.row,start.column),1==cmp?2:0==cmp?1:0):-1==cmp?-2:(cmp=this.compare(start.row,start.column),-1==cmp?-1:1==cmp?42:0)},this.comparePoint=function(p){return this.compare(p.row,p.column)},this.containsRange=function(range){return 0==this.comparePoint(range.start)&&0==this.comparePoint(range.end)},this.intersects=function(range){var cmp=this.compareRange(range);return-1==cmp||0==cmp||1==cmp},this.isEnd=function(row,column){return this.end.row==row&&this.end.column==column},this.isStart=function(row,column){return this.start.row==row&&this.start.column==column},this.setStart=function(row,column){"object"==typeof row?(this.start.column=row.column,this.start.row=row.row):(this.start.row=row,this.start.column=column)},this.setEnd=function(row,column){"object"==typeof row?(this.end.column=row.column,this.end.row=row.row):(this.end.row=row,this.end.column=column)},this.inside=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)||this.isStart(row,column)?!1:!0:!1},this.insideStart=function(row,column){return 0==this.compare(row,column)?this.isEnd(row,column)?!1:!0:!1},this.insideEnd=function(row,column){return 0==this.compare(row,column)?this.isStart(row,column)?!1:!0:!1},this.compare=function(row,column){return this.isMultiLine()||row!==this.start.row?this.start.row>row?-1:row>this.end.row?1:this.start.row===row?column>=this.start.column?0:-1:this.end.row===row?this.end.column>=column?0:1:0:this.start.column>column?-1:column>this.end.column?1:0},this.compareStart=function(row,column){return this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.compareEnd=function(row,column){return this.end.row==row&&this.end.column==column?1:this.compare(row,column)},this.compareInside=function(row,column){return this.end.row==row&&this.end.column==column?1:this.start.row==row&&this.start.column==column?-1:this.compare(row,column)},this.clipRows=function(firstRow,lastRow){if(this.end.row>lastRow)var end={row:lastRow+1,column:0};else if(firstRow>this.end.row)var end={row:firstRow,column:0};if(this.start.row>lastRow)var start={row:lastRow+1,column:0};else if(firstRow>this.start.row)var start={row:firstRow,column:0};return Range.fromPoints(start||this.start,end||this.end)},this.extend=function(row,column){var cmp=this.compare(row,column);if(0==cmp)return this;if(-1==cmp)var start={row:row,column:column};else var end={row:row,column:column};return Range.fromPoints(start||this.start,end||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return Range.fromPoints(this.start,this.end)},this.collapseRows=function(){return 0==this.end.column?new Range(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new Range(this.start.row,0,this.end.row,0)},this.toScreenRange=function(session){var screenPosStart=session.documentToScreenPosition(this.start),screenPosEnd=session.documentToScreenPosition(this.end);return new Range(screenPosStart.row,screenPosStart.column,screenPosEnd.row,screenPosEnd.column)},this.moveBy=function(row,column){this.start.row+=row,this.start.column+=column,this.end.row+=row,this.end.column+=column}}).call(Range.prototype),Range.fromPoints=function(start,end){return new Range(start.row,start.column,end.row,end.column)},Range.comparePoints=comparePoints,Range.comparePoints=function(p1,p2){return p1.row-p2.row||p1.column-p2.column},exports.Range=Range}),ace.define("ace/apply_delta",["require","exports","module"],function(acequire,exports){"use strict";exports.applyDelta=function(docLines,delta){var row=delta.start.row,startColumn=delta.start.column,line=docLines[row]||"";switch(delta.action){case"insert":var lines=delta.lines;if(1===lines.length)docLines[row]=line.substring(0,startColumn)+delta.lines[0]+line.substring(startColumn);else{var args=[row,1].concat(delta.lines);docLines.splice.apply(docLines,args),docLines[row]=line.substring(0,startColumn)+docLines[row],docLines[row+delta.lines.length-1]+=line.substring(startColumn)}break;case"remove":var endColumn=delta.end.column,endRow=delta.end.row;row===endRow?docLines[row]=line.substring(0,startColumn)+line.substring(endColumn):docLines.splice(row,endRow-row+1,line.substring(0,startColumn)+docLines[endRow].substring(endColumn))}}}),ace.define("ace/lib/event_emitter",["require","exports","module"],function(acequire,exports){"use strict";var EventEmitter={},stopPropagation=function(){this.propagationStopped=!0},preventDefault=function(){this.defaultPrevented=!0};EventEmitter._emit=EventEmitter._dispatchEvent=function(eventName,e){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var listeners=this._eventRegistry[eventName]||[],defaultHandler=this._defaultHandlers[eventName];if(listeners.length||defaultHandler){"object"==typeof e&&e||(e={}),e.type||(e.type=eventName),e.stopPropagation||(e.stopPropagation=stopPropagation),e.preventDefault||(e.preventDefault=preventDefault),listeners=listeners.slice();for(var i=0;listeners.length>i&&(listeners[i](e,this),!e.propagationStopped);i++);return defaultHandler&&!e.defaultPrevented?defaultHandler(e,this):void 0}},EventEmitter._signal=function(eventName,e){var listeners=(this._eventRegistry||{})[eventName];if(listeners){listeners=listeners.slice();for(var i=0;listeners.length>i;i++)listeners[i](e,this)}},EventEmitter.once=function(eventName,callback){var _self=this;callback&&this.addEventListener(eventName,function newCallback(){_self.removeEventListener(eventName,newCallback),callback.apply(null,arguments)})},EventEmitter.setDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers||(handlers=this._defaultHandlers={_disabled_:{}}),handlers[eventName]){var old=handlers[eventName],disabled=handlers._disabled_[eventName];disabled||(handlers._disabled_[eventName]=disabled=[]),disabled.push(old);var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}handlers[eventName]=callback},EventEmitter.removeDefaultHandler=function(eventName,callback){var handlers=this._defaultHandlers;if(handlers){var disabled=handlers._disabled_[eventName];if(handlers[eventName]==callback)handlers[eventName],disabled&&this.setDefaultHandler(eventName,disabled.pop());else if(disabled){var i=disabled.indexOf(callback);-1!=i&&disabled.splice(i,1)}}},EventEmitter.on=EventEmitter.addEventListener=function(eventName,callback,capturing){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];return listeners||(listeners=this._eventRegistry[eventName]=[]),-1==listeners.indexOf(callback)&&listeners[capturing?"unshift":"push"](callback),callback},EventEmitter.off=EventEmitter.removeListener=EventEmitter.removeEventListener=function(eventName,callback){this._eventRegistry=this._eventRegistry||{};var listeners=this._eventRegistry[eventName];if(listeners){var index=listeners.indexOf(callback);-1!==index&&listeners.splice(index,1)}},EventEmitter.removeAllListeners=function(eventName){this._eventRegistry&&(this._eventRegistry[eventName]=[])},exports.EventEmitter=EventEmitter}),ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(acequire,exports){"use strict";var oop=acequire("./lib/oop"),EventEmitter=acequire("./lib/event_emitter").EventEmitter,Anchor=exports.Anchor=function(doc,row,column){this.$onChange=this.onChange.bind(this),this.attach(doc),column===void 0?this.setPosition(row.row,row.column):this.setPosition(row,column)};(function(){function $pointsInOrder(point1,point2,equalPointsInOrder){var bColIsAfter=equalPointsInOrder?point1.column<=point2.column:point1.columnthis.row)){var point=$getTransformedPoint(delta,{row:this.row,column:this.column},this.$insertRight);this.setPosition(point.row,point.column,!0)}},this.setPosition=function(row,column,noClip){var pos;if(pos=noClip?{row:row,column:column}:this.$clipPositionToDocument(row,column),this.row!=pos.row||this.column!=pos.column){var old={row:this.row,column:this.column};this.row=pos.row,this.column=pos.column,this._signal("change",{old:old,value:pos})}},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(doc){this.document=doc||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(row,column){var pos={};return row>=this.document.getLength()?(pos.row=Math.max(0,this.document.getLength()-1),pos.column=this.document.getLine(pos.row).length):0>row?(pos.row=0,pos.column=0):(pos.row=row,pos.column=Math.min(this.document.getLine(pos.row).length,Math.max(0,column))),0>column&&(pos.column=0),pos}}).call(Anchor.prototype)}),ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(acequire,exports){"use strict";var oop=acequire("./lib/oop"),applyDelta=acequire("./apply_delta").applyDelta,EventEmitter=acequire("./lib/event_emitter").EventEmitter,Range=acequire("./range").Range,Anchor=acequire("./anchor").Anchor,Document=function(textOrLines){this.$lines=[""],0===textOrLines.length?this.$lines=[""]:Array.isArray(textOrLines)?this.insertMergedLines({row:0,column:0},textOrLines):this.insert({row:0,column:0},textOrLines)};(function(){oop.implement(this,EventEmitter),this.setValue=function(text){var len=this.getLength()-1;this.remove(new Range(0,0,len,this.getLine(len).length)),this.insert({row:0,column:0},text)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(row,column){return new Anchor(this,row,column)},this.$split=0==="aaa".split(/a/).length?function(text){return text.replace(/\\r\\n|\\r/g,"\\n").split("\\n")}:function(text){return text.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(text){var match=text.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=match?match[1]:"\\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\\r\\n";case"unix":return"\\n";default:return this.$autoNewLine||"\\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(newLineMode){this.$newLineMode!==newLineMode&&(this.$newLineMode=newLineMode,this._signal("changeNewLineMode"))},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(text){return"\\r\\n"==text||"\\r"==text||"\\n"==text},this.getLine=function(row){return this.$lines[row]||""},this.getLines=function(firstRow,lastRow){return this.$lines.slice(firstRow,lastRow+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(range){return this.getLinesForRange(range).join(this.getNewLineCharacter())},this.getLinesForRange=function(range){var lines;if(range.start.row===range.end.row)lines=[this.getLine(range.start.row).substring(range.start.column,range.end.column)];else{lines=this.getLines(range.start.row,range.end.row),lines[0]=(lines[0]||"").substring(range.start.column);var l=lines.length-1;range.end.row-range.start.row==l&&(lines[l]=lines[l].substring(0,range.end.column))}return lines},this.insertLines=function(row,lines){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(row,lines)},this.removeLines=function(firstRow,lastRow){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(firstRow,lastRow)},this.insertNewLine=function(position){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead."),this.insertMergedLines(position,["",""])},this.insert=function(position,text){return 1>=this.getLength()&&this.$detectNewLine(text),this.insertMergedLines(position,this.$split(text))},this.insertInLine=function(position,text){var start=this.clippedPos(position.row,position.column),end=this.pos(position.row,position.column+text.length);return this.applyDelta({start:start,end:end,action:"insert",lines:[text]},!0),this.clonePos(end)},this.clippedPos=function(row,column){var length=this.getLength();void 0===row?row=length:0>row?row=0:row>=length&&(row=length-1,column=void 0);var line=this.getLine(row);return void 0==column&&(column=line.length),column=Math.min(Math.max(column,0),line.length),{row:row,column:column}},this.clonePos=function(pos){return{row:pos.row,column:pos.column}},this.pos=function(row,column){return{row:row,column:column}},this.$clipPosition=function(position){var length=this.getLength();return position.row>=length?(position.row=Math.max(0,length-1),position.column=this.getLine(length-1).length):(position.row=Math.max(0,position.row),position.column=Math.min(Math.max(position.column,0),this.getLine(position.row).length)),position},this.insertFullLines=function(row,lines){row=Math.min(Math.max(row,0),this.getLength());var column=0;this.getLength()>row?(lines=lines.concat([""]),column=0):(lines=[""].concat(lines),row--,column=this.$lines[row].length),this.insertMergedLines({row:row,column:column},lines)},this.insertMergedLines=function(position,lines){var start=this.clippedPos(position.row,position.column),end={row:start.row+lines.length-1,column:(1==lines.length?start.column:0)+lines[lines.length-1].length};return this.applyDelta({start:start,end:end,action:"insert",lines:lines}),this.clonePos(end)},this.remove=function(range){var start=this.clippedPos(range.start.row,range.start.column),end=this.clippedPos(range.end.row,range.end.column);return this.applyDelta({start:start,end:end,action:"remove",lines:this.getLinesForRange({start:start,end:end})}),this.clonePos(start)},this.removeInLine=function(row,startColumn,endColumn){var start=this.clippedPos(row,startColumn),end=this.clippedPos(row,endColumn);return this.applyDelta({start:start,end:end,action:"remove",lines:this.getLinesForRange({start:start,end:end})},!0),this.clonePos(start)},this.removeFullLines=function(firstRow,lastRow){firstRow=Math.min(Math.max(0,firstRow),this.getLength()-1),lastRow=Math.min(Math.max(0,lastRow),this.getLength()-1);var deleteFirstNewLine=lastRow==this.getLength()-1&&firstRow>0,deleteLastNewLine=this.getLength()-1>lastRow,startRow=deleteFirstNewLine?firstRow-1:firstRow,startCol=deleteFirstNewLine?this.getLine(startRow).length:0,endRow=deleteLastNewLine?lastRow+1:lastRow,endCol=deleteLastNewLine?0:this.getLine(endRow).length,range=new Range(startRow,startCol,endRow,endCol),deletedLines=this.$lines.slice(firstRow,lastRow+1);return this.applyDelta({start:range.start,end:range.end,action:"remove",lines:this.getLinesForRange(range)}),deletedLines},this.removeNewLine=function(row){this.getLength()-1>row&&row>=0&&this.applyDelta({start:this.pos(row,this.getLine(row).length),end:this.pos(row+1,0),action:"remove",lines:["",""]})},this.replace=function(range,text){if(range instanceof Range||(range=Range.fromPoints(range.start,range.end)),0===text.length&&range.isEmpty())return range.start;if(text==this.getTextRange(range))return range.end;this.remove(range);var end;return end=text?this.insert(range.start,text):range.start},this.applyDeltas=function(deltas){for(var i=0;deltas.length>i;i++)this.applyDelta(deltas[i])},this.revertDeltas=function(deltas){for(var i=deltas.length-1;i>=0;i--)this.revertDelta(deltas[i])},this.applyDelta=function(delta,doNotValidate){var isInsert="insert"==delta.action;(isInsert?1>=delta.lines.length&&!delta.lines[0]:!Range.comparePoints(delta.start,delta.end))||(isInsert&&delta.lines.length>2e4&&this.$splitAndapplyLargeDelta(delta,2e4),applyDelta(this.$lines,delta,doNotValidate),this._signal("change",delta))},this.$splitAndapplyLargeDelta=function(delta,MAX){for(var lines=delta.lines,l=lines.length,row=delta.start.row,column=delta.start.column,from=0,to=0;;){from=to,to+=MAX-1;var chunk=lines.slice(from,to);if(to>l){delta.lines=chunk,delta.start.row=row+from,delta.start.column=column;break}chunk.push(""),this.applyDelta({start:this.pos(row+from,column),end:this.pos(row+to,column=0),action:delta.action,lines:chunk},!0)}},this.revertDelta=function(delta){this.applyDelta({start:this.clonePos(delta.start),end:this.clonePos(delta.end),action:"insert"==delta.action?"remove":"insert",lines:delta.lines.slice()})},this.indexToPosition=function(index,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,i=startRow||0,l=lines.length;l>i;i++)if(index-=lines[i].length+newlineLength,0>index)return{row:i,column:index+lines[i].length+newlineLength};return{row:l-1,column:lines[l-1].length}},this.positionToIndex=function(pos,startRow){for(var lines=this.$lines||this.getAllLines(),newlineLength=this.getNewLineCharacter().length,index=0,row=Math.min(pos.row,lines.length),i=startRow||0;row>i;++i)index+=lines[i].length+newlineLength;return index+pos.column}}).call(Document.prototype),exports.Document=Document}),ace.define("ace/lib/lang",["require","exports","module"],function(acequire,exports){"use strict";exports.last=function(a){return a[a.length-1]},exports.stringReverse=function(string){return string.split("").reverse().join("")},exports.stringRepeat=function(string,count){for(var result="";count>0;)1&count&&(result+=string),(count>>=1)&&(string+=string);return result};var trimBeginRegexp=/^\\s\\s*/,trimEndRegexp=/\\s\\s*$/;exports.stringTrimLeft=function(string){return string.replace(trimBeginRegexp,"")},exports.stringTrimRight=function(string){return string.replace(trimEndRegexp,"")},exports.copyObject=function(obj){var copy={};for(var key in obj)copy[key]=obj[key];return copy},exports.copyArray=function(array){for(var copy=[],i=0,l=array.length;l>i;i++)copy[i]=array[i]&&"object"==typeof array[i]?this.copyObject(array[i]):array[i];return copy},exports.deepCopy=function deepCopy(obj){if("object"!=typeof obj||!obj)return obj;var copy;if(Array.isArray(obj)){copy=[];for(var key=0;obj.length>key;key++)copy[key]=deepCopy(obj[key]);return copy}var cons=obj.constructor;if(cons===RegExp)return obj;copy=cons();for(var key in obj)copy[key]=deepCopy(obj[key]);return copy},exports.arrayToMap=function(arr){for(var map={},i=0;arr.length>i;i++)map[arr[i]]=1;return map},exports.createMap=function(props){var map=Object.create(null);for(var i in props)map[i]=props[i];return map},exports.arrayRemove=function(array,value){for(var i=0;array.length>=i;i++)value===array[i]&&array.splice(i,1)},exports.escapeRegExp=function(str){return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,"\\\\$1")},exports.escapeHTML=function(str){return str.replace(/&/g,"&").replace(/"/g,""").replace(/\'/g,"'").replace(/i;i+=2){if(Array.isArray(data[i+1]))var d={action:"insert",start:data[i],lines:data[i+1]};else var d={action:"remove",start:data[i],end:data[i+1]};doc.applyDelta(d,!0)}return _self.$timeout?deferredUpdate.schedule(_self.$timeout):(_self.onUpdate(),void 0)})};(function(){this.$timeout=500,this.setTimeout=function(timeout){this.$timeout=timeout},this.setValue=function(value){this.doc.setValue(value),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(callbackId){this.sender.callback(this.doc.getValue(),callbackId)},this.onUpdate=function(){},this.isPending=function(){return this.deferredUpdate.isPending()}}).call(Mirror.prototype)}),ace.define("ace/mode/json/json_parse",["require","exports","module"],function(){"use strict";var at,ch,text,value,escapee={\'"\':\'"\',"\\\\":"\\\\","/":"/",b:"\\b",f:"\\f",n:"\\n",r:"\\r",t:" "},error=function(m){throw{name:"SyntaxError",message:m,at:at,text:text}},next=function(c){return c&&c!==ch&&error("Expected \'"+c+"\' instead of \'"+ch+"\'"),ch=text.charAt(at),at+=1,ch},number=function(){var number,string="";for("-"===ch&&(string="-",next("-"));ch>="0"&&"9">=ch;)string+=ch,next();if("."===ch)for(string+=".";next()&&ch>="0"&&"9">=ch;)string+=ch;if("e"===ch||"E"===ch)for(string+=ch,next(),("-"===ch||"+"===ch)&&(string+=ch,next());ch>="0"&&"9">=ch;)string+=ch,next();return number=+string,isNaN(number)?(error("Bad number"),void 0):number},string=function(){var hex,i,uffff,string="";if(\'"\'===ch)for(;next();){if(\'"\'===ch)return next(),string;if("\\\\"===ch)if(next(),"u"===ch){for(uffff=0,i=0;4>i&&(hex=parseInt(next(),16),isFinite(hex));i+=1)uffff=16*uffff+hex;string+=String.fromCharCode(uffff)}else{if("string"!=typeof escapee[ch])break;string+=escapee[ch]}else string+=ch}error("Bad string")},white=function(){for(;ch&&" ">=ch;)next()},word=function(){switch(ch){case"t":return next("t"),next("r"),next("u"),next("e"),!0;case"f":return next("f"),next("a"),next("l"),next("s"),next("e"),!1;case"n":return next("n"),next("u"),next("l"),next("l"),null}error("Unexpected \'"+ch+"\'")},array=function(){var array=[];if("["===ch){if(next("["),white(),"]"===ch)return next("]"),array;for(;ch;){if(array.push(value()),white(),"]"===ch)return next("]"),array;next(","),white()}}error("Bad array")},object=function(){var key,object={};if("{"===ch){if(next("{"),white(),"}"===ch)return next("}"),object;for(;ch;){if(key=string(),white(),next(":"),Object.hasOwnProperty.call(object,key)&&error(\'Duplicate key "\'+key+\'"\'),object[key]=value(),white(),"}"===ch)return next("}"),object;next(","),white()}}error("Bad object")};return value=function(){switch(white(),ch){case"{":return object();case"[":return array();case\'"\':return string();case"-":return number();default:return ch>="0"&&"9">=ch?number():word()}},function(source,reviver){var result;return text=source,at=0,ch=" ",result=value(),white(),ch&&error("Syntax error"),"function"==typeof reviver?function walk(holder,key){var k,v,value=holder[key];if(value&&"object"==typeof value)for(k in value)Object.hasOwnProperty.call(value,k)&&(v=walk(value,k),void 0!==v?value[k]=v:delete value[k]);return reviver.call(holder,key,value)}({"":result},""):result}}),ace.define("ace/mode/json_worker",["require","exports","module","ace/lib/oop","ace/worker/mirror","ace/mode/json/json_parse"],function(acequire,exports){"use strict";var oop=acequire("../lib/oop"),Mirror=acequire("../worker/mirror").Mirror,parse=acequire("./json/json_parse"),JsonWorker=exports.JsonWorker=function(sender){Mirror.call(this,sender),this.setTimeout(200)};oop.inherits(JsonWorker,Mirror),function(){this.onUpdate=function(){var value=this.doc.getValue(),errors=[];try{value&&parse(value)}catch(e){var pos=this.doc.indexToPosition(e.at-1);errors.push({row:pos.row,column:pos.column,text:e.message,type:"error"})}this.sender.emit("annotate",errors)}}.call(JsonWorker.prototype)}),ace.define("ace/lib/es5-shim",["require","exports","module"],function(){function Empty(){}function doesDefinePropertyWork(object){try{return Object.defineProperty(object,"sentinel",{}),"sentinel"in object}catch(exception){}}function toInteger(n){return n=+n,n!==n?n=0:0!==n&&n!==1/0&&n!==-(1/0)&&(n=(n>0||-1)*Math.floor(Math.abs(n))),n}Function.prototype.bind||(Function.prototype.bind=function(that){var target=this;if("function"!=typeof target)throw new TypeError("Function.prototype.bind called on incompatible "+target);var args=slice.call(arguments,1),bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));return Object(result)===result?result:this}return target.apply(that,args.concat(slice.call(arguments)))};return target.prototype&&(Empty.prototype=target.prototype,bound.prototype=new Empty,Empty.prototype=null),bound});var defineGetter,defineSetter,lookupGetter,lookupSetter,supportsAccessors,call=Function.prototype.call,prototypeOfArray=Array.prototype,prototypeOfObject=Object.prototype,slice=prototypeOfArray.slice,_toString=call.bind(prototypeOfObject.toString),owns=call.bind(prototypeOfObject.hasOwnProperty);if((supportsAccessors=owns(prototypeOfObject,"__defineGetter__"))&&(defineGetter=call.bind(prototypeOfObject.__defineGetter__),defineSetter=call.bind(prototypeOfObject.__defineSetter__),lookupGetter=call.bind(prototypeOfObject.__lookupGetter__),lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)),2!=[1,2].splice(0).length)if(function(){function makeArray(l){var a=Array(l+2);return a[0]=a[1]=0,a}var lengthBefore,array=[];return array.splice.apply(array,makeArray(20)),array.splice.apply(array,makeArray(26)),lengthBefore=array.length,array.splice(5,0,"XXX"),lengthBefore+1==array.length,lengthBefore+1==array.length?!0:void 0\n}()){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){return arguments.length?array_splice.apply(this,[void 0===start?0:start,void 0===deleteCount?this.length-start:deleteCount].concat(slice.call(arguments,2))):[]}}else Array.prototype.splice=function(pos,removeCount){var length=this.length;pos>0?pos>length&&(pos=length):void 0==pos?pos=0:0>pos&&(pos=Math.max(length+pos,0)),length>pos+removeCount||(removeCount=length-pos);var removed=this.slice(pos,pos+removeCount),insert=slice.call(arguments,2),add=insert.length;if(pos===length)add&&this.push.apply(this,insert);else{var remove=Math.min(removeCount,length-pos),tailOldPos=pos+remove,tailNewPos=tailOldPos+add-remove,tailCount=length-tailOldPos,lengthAfterRemove=length-remove;if(tailOldPos>tailNewPos)for(var i=0;tailCount>i;++i)this[tailNewPos+i]=this[tailOldPos+i];else if(tailNewPos>tailOldPos)for(i=tailCount;i--;)this[tailNewPos+i]=this[tailOldPos+i];if(add&&pos===lengthAfterRemove)this.length=lengthAfterRemove,this.push.apply(this,insert);else for(this.length=lengthAfterRemove+add,i=0;add>i;++i)this[pos+i]=insert[i]}return removed};Array.isArray||(Array.isArray=function(obj){return"[object Array]"==_toString(obj)});var boxedString=Object("a"),splitString="a"!=boxedString[0]||!(0 in boxedString);if(Array.prototype.forEach||(Array.prototype.forEach=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,thisp=arguments[1],i=-1,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError;for(;length>++i;)i in self&&fun.call(thisp,self[i],i,object)}),Array.prototype.map||(Array.prototype.map=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)i in self&&(result[i]=fun.call(thisp,self[i],i,object));return result}),Array.prototype.filter||(Array.prototype.filter=function(fun){var value,object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,result=[],thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)i in self&&(value=self[i],fun.call(thisp,value,i,object)&&result.push(value));return result}),Array.prototype.every||(Array.prototype.every=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0,thisp=arguments[1];if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");for(var i=0;length>i;i++)if(i in self&&fun.call(thisp,self[i],i,object))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");if(!length&&1==arguments.length)throw new TypeError("reduce of empty array with no initial value");var result,i=0;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError("reduce of empty array with no initial value")}for(;length>i;i++)i in self&&(result=fun.call(void 0,result,self[i],i,object));return result}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(fun){var object=toObject(this),self=splitString&&"[object String]"==_toString(this)?this.split(""):object,length=self.length>>>0;if("[object Function]"!=_toString(fun))throw new TypeError(fun+" is not a function");if(!length&&1==arguments.length)throw new TypeError("reduceRight of empty array with no initial value");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else for(;;){if(i in self){result=self[i--];break}if(0>--i)throw new TypeError("reduceRight of empty array with no initial value")}do i in this&&(result=fun.call(void 0,result,self[i],i,object));while(i--);return result}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(sought){var self=splitString&&"[object String]"==_toString(this)?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;for(arguments.length>1&&(i=toInteger(arguments[1])),i=i>=0?i:Math.max(0,length+i);length>i;i++)if(i in self&&self[i]===sought)return i;return-1}),Array.prototype.lastIndexOf&&-1==[0,1].lastIndexOf(0,-3)||(Array.prototype.lastIndexOf=function(sought){var self=splitString&&"[object String]"==_toString(this)?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;for(arguments.length>1&&(i=Math.min(i,toInteger(arguments[1]))),i=i>=0?i:length-Math.abs(i);i>=0;i--)if(i in self&&sought===self[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(object){return object.__proto__||(object.constructor?object.constructor.prototype:prototypeOfObject)}),!Object.getOwnPropertyDescriptor){var ERR_NON_OBJECT="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(object,property){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT+object);if(owns(object,property)){var descriptor,getter,setter;if(descriptor={enumerable:!0,configurable:!0},supportsAccessors){var prototype=object.__proto__;object.__proto__=prototypeOfObject;var getter=lookupGetter(object,property),setter=lookupSetter(object,property);if(object.__proto__=prototype,getter||setter)return getter&&(descriptor.get=getter),setter&&(descriptor.set=setter),descriptor}return descriptor.value=object[property],descriptor}}}if(Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(object){return Object.keys(object)}),!Object.create){var createEmpty;createEmpty=null===Object.prototype.__proto__?function(){return{__proto__:null}}:function(){var empty={};for(var i in empty)empty[i]=null;return empty.constructor=empty.hasOwnProperty=empty.propertyIsEnumerable=empty.isPrototypeOf=empty.toLocaleString=empty.toString=empty.valueOf=empty.__proto__=null,empty},Object.create=function(prototype,properties){var object;if(null===prototype)object=createEmpty();else{if("object"!=typeof prototype)throw new TypeError("typeof prototype["+typeof prototype+"] != \'object\'");var Type=function(){};Type.prototype=prototype,object=new Type,object.__proto__=prototype}return void 0!==properties&&Object.defineProperties(object,properties),object}}if(Object.defineProperty){var definePropertyWorksOnObject=doesDefinePropertyWork({}),definePropertyWorksOnDom="undefined"==typeof document||doesDefinePropertyWork(document.createElement("div"));if(!definePropertyWorksOnObject||!definePropertyWorksOnDom)var definePropertyFallback=Object.defineProperty}if(!Object.defineProperty||definePropertyFallback){var ERR_NON_OBJECT_DESCRIPTOR="Property description must be an object: ",ERR_NON_OBJECT_TARGET="Object.defineProperty called on non-object: ",ERR_ACCESSORS_NOT_SUPPORTED="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(object,property,descriptor){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError(ERR_NON_OBJECT_TARGET+object);if("object"!=typeof descriptor&&"function"!=typeof descriptor||null===descriptor)throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR+descriptor);if(definePropertyFallback)try{return definePropertyFallback.call(Object,object,property,descriptor)}catch(exception){}if(owns(descriptor,"value"))if(supportsAccessors&&(lookupGetter(object,property)||lookupSetter(object,property))){var prototype=object.__proto__;object.__proto__=prototypeOfObject,delete object[property],object[property]=descriptor.value,object.__proto__=prototype}else object[property]=descriptor.value;else{if(!supportsAccessors)throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);owns(descriptor,"get")&&defineGetter(object,property,descriptor.get),owns(descriptor,"set")&&defineSetter(object,property,descriptor.set)}return object}}Object.defineProperties||(Object.defineProperties=function(object,properties){for(var property in properties)owns(properties,property)&&Object.defineProperty(object,property,properties[property]);return object}),Object.seal||(Object.seal=function(object){return object}),Object.freeze||(Object.freeze=function(object){return object});try{Object.freeze(function(){})}catch(exception){Object.freeze=function(freezeObject){return function(object){return"function"==typeof object?object:freezeObject(object)}}(Object.freeze)}if(Object.preventExtensions||(Object.preventExtensions=function(object){return object}),Object.isSealed||(Object.isSealed=function(){return!1}),Object.isFrozen||(Object.isFrozen=function(){return!1}),Object.isExtensible||(Object.isExtensible=function(object){if(Object(object)===object)throw new TypeError;for(var name="";owns(object,name);)name+="?";object[name]=!0;var returnValue=owns(object,name);return delete object[name],returnValue}),!Object.keys){var hasDontEnumBug=!0,dontEnums=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],dontEnumsLength=dontEnums.length;for(var key in{toString:null})hasDontEnumBug=!1;Object.keys=function(object){if("object"!=typeof object&&"function"!=typeof object||null===object)throw new TypeError("Object.keys called on a non-object");var keys=[];for(var name in object)owns(object,name)&&keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;ii>i;i++){var dontEnum=dontEnums[i];owns(object,dontEnum)&&keys.push(dontEnum)}return keys}}Date.now||(Date.now=function(){return(new Date).getTime()});var ws=" \\n\x0B\\f\\r   ᠎              \\u2028\\u2029\ufeff";if(!String.prototype.trim||ws.trim()){ws="["+ws+"]";var trimBeginRegexp=RegExp("^"+ws+ws+"*"),trimEndRegexp=RegExp(ws+ws+"*$");String.prototype.trim=function(){return(this+"").replace(trimBeginRegexp,"").replace(trimEndRegexp,"")}}var toObject=function(o){if(null==o)throw new TypeError("can\'t convert "+o+" to object");return Object(o)}});'; +},function(e,t){ace.define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"],function(e,t,i){"use strict";var n=e("../lib/dom"),r=e("../lib/lang"),o=e("../lib/event"),s=" .ace_search { background-color: #ddd; border: 1px solid #cbcbcb; border-top: 0 none; max-width: 325px; overflow: hidden; margin: 0; padding: 4px; padding-right: 6px; padding-bottom: 0; position: absolute; top: 0px; z-index: 99; white-space: normal; } .ace_search.left { border-left: 0 none; border-radius: 0px 0px 5px 0px; left: 0; } .ace_search.right { border-radius: 0px 0px 0px 5px; border-right: 0 none; right: 0; } .ace_search_form, .ace_replace_form { border-radius: 3px; border: 1px solid #cbcbcb; float: left; margin-bottom: 4px; overflow: hidden; } .ace_search_form.ace_nomatch { outline: 1px solid red; } .ace_search_field { background-color: white; border-right: 1px solid #cbcbcb; border: 0 none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; float: left; height: 22px; outline: 0; padding: 0 7px; width: 214px; margin: 0; } .ace_searchbtn, .ace_replacebtn { background: #fff; border: 0 none; border-left: 1px solid #dcdcdc; cursor: pointer; float: left; height: 22px; margin: 0; position: relative; } .ace_searchbtn:last-child, .ace_replacebtn:last-child { border-top-right-radius: 3px; border-bottom-right-radius: 3px; } .ace_searchbtn:disabled { background: none; cursor: default; } .ace_searchbtn { background-position: 50% 50%; background-repeat: no-repeat; width: 27px; } .ace_searchbtn.prev { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); } .ace_searchbtn.next { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); } .ace_searchbtn_close { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0; border-radius: 50%; border: 0 none; color: #656565; cursor: pointer; float: right; font: 16px/16px Arial; height: 14px; margin: 5px 1px 9px 5px; padding: 0; text-align: center; width: 14px; } .ace_searchbtn_close:hover { background-color: #656565; background-position: 50% 100%; color: white; } .ace_replacebtn.prev { width: 54px } .ace_replacebtn.next { width: 27px } .ace_button { margin-left: 2px; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; -ms-user-select: none; user-select: none; overflow: hidden; opacity: 0.7; border: 1px solid rgba(100,100,100,0.23); padding: 1px; -moz-box-sizing: border-box; box-sizing: border-box; color: black; } .ace_button:hover { background-color: #eee; opacity:1; } .ace_button:active { background-color: #ddd; } .ace_button.checked { border-color: #3399ff; opacity:1; } .ace_search_options{ margin-bottom: 3px; text-align: right; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; -ms-user-select: none; user-select: none; }",a=e("../keyboard/hash_handler").HashHandler,l=e("../lib/keys");n.importCssString(s,"ace_searchbox");var c=''.replace(/>\s+/g,">"),h=function(e,t,i){var r=n.createElement("div");r.innerHTML=c,this.element=r.firstChild,this.$init(),this.setEditor(e)};(function(){this.setEditor=function(e){e.searchBox=this,e.container.appendChild(this.element),this.editor=e},this.$initElements=function(e){this.searchBox=e.querySelector(".ace_search_form"),this.replaceBox=e.querySelector(".ace_replace_form"),this.searchOptions=e.querySelector(".ace_search_options"),this.regExpOption=e.querySelector("[action=toggleRegexpMode]"),this.caseSensitiveOption=e.querySelector("[action=toggleCaseSensitive]"),this.wholeWordOption=e.querySelector("[action=toggleWholeWords]"),this.searchInput=this.searchBox.querySelector(".ace_search_field"),this.replaceInput=this.replaceBox.querySelector(".ace_search_field")},this.$init=function(){var e=this.element;this.$initElements(e);var t=this;o.addListener(e,"mousedown",function(e){setTimeout(function(){t.activeInput.focus()},0),o.stopPropagation(e)}),o.addListener(e,"click",function(e){var i=e.target||e.srcElement,n=i.getAttribute("action");n&&t[n]?t[n]():t.$searchBarKb.commands[n]&&t.$searchBarKb.commands[n].exec(t),o.stopPropagation(e)}),o.addCommandKeyListener(e,function(e,i,n){var r=l.keyCodeToString(n),s=t.$searchBarKb.findKeyCommand(i,r);s&&s.exec&&(s.exec(t),o.stopEvent(e))}),this.$onChange=r.delayedCall(function(){t.find(!1,!1)}),o.addListener(this.searchInput,"input",function(){t.$onChange.schedule(20)}),o.addListener(this.searchInput,"focus",function(){t.activeInput=t.searchInput,t.searchInput.value&&t.highlight()}),o.addListener(this.replaceInput,"focus",function(){t.activeInput=t.replaceInput,t.searchInput.value&&t.highlight()})},this.$closeSearchBarKb=new a([{bindKey:"Esc",name:"closeSearchBar",exec:function(e){e.searchBox.hide()}}]),this.$searchBarKb=new a,this.$searchBarKb.bindKeys({"Ctrl-f|Command-f":function(e){var t=e.isReplace=!e.isReplace;e.replaceBox.style.display=t?"":"none",e.searchInput.focus()},"Ctrl-H|Command-Option-F":function(e){e.replaceBox.style.display="",e.replaceInput.focus()},"Ctrl-G|Command-G":function(e){e.findNext()},"Ctrl-Shift-G|Command-Shift-G":function(e){e.findPrev()},esc:function(e){setTimeout(function(){e.hide()})},Return:function(e){e.activeInput==e.replaceInput&&e.replace(),e.findNext()},"Shift-Return":function(e){e.activeInput==e.replaceInput&&e.replace(),e.findPrev()},"Alt-Return":function(e){e.activeInput==e.replaceInput&&e.replaceAll(),e.findAll()},Tab:function(e){(e.activeInput==e.replaceInput?e.searchInput:e.replaceInput).focus()}}),this.$searchBarKb.addCommands([{name:"toggleRegexpMode",bindKey:{win:"Alt-R|Alt-/",mac:"Ctrl-Alt-R|Ctrl-Alt-/"},exec:function(e){e.regExpOption.checked=!e.regExpOption.checked,e.$syncOptions()}},{name:"toggleCaseSensitive",bindKey:{win:"Alt-C|Alt-I",mac:"Ctrl-Alt-R|Ctrl-Alt-I"},exec:function(e){e.caseSensitiveOption.checked=!e.caseSensitiveOption.checked,e.$syncOptions()}},{name:"toggleWholeWords",bindKey:{win:"Alt-B|Alt-W",mac:"Ctrl-Alt-B|Ctrl-Alt-W"},exec:function(e){e.wholeWordOption.checked=!e.wholeWordOption.checked,e.$syncOptions()}}]),this.$syncOptions=function(){n.setCssClass(this.regExpOption,"checked",this.regExpOption.checked),n.setCssClass(this.wholeWordOption,"checked",this.wholeWordOption.checked),n.setCssClass(this.caseSensitiveOption,"checked",this.caseSensitiveOption.checked),this.find(!1,!1)},this.highlight=function(e){this.editor.session.highlight(e||this.editor.$search.$options.re),this.editor.renderer.updateBackMarkers()},this.find=function(e,t,i){var r=this.editor.find(this.searchInput.value,{skipCurrent:e,backwards:t,wrap:!0,regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked,preventScroll:i}),o=!r&&this.searchInput.value;n.setCssClass(this.searchBox,"ace_nomatch",o),this.editor._emit("findSearchBox",{match:!o}),this.highlight()},this.findNext=function(){this.find(!0,!1)},this.findPrev=function(){this.find(!0,!0)},this.findAll=function(){var e=this.editor.findAll(this.searchInput.value,{regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked}),t=!e&&this.searchInput.value;n.setCssClass(this.searchBox,"ace_nomatch",t),this.editor._emit("findSearchBox",{match:!t}),this.highlight(),this.hide()},this.replace=function(){this.editor.getReadOnly()||this.editor.replace(this.replaceInput.value)},this.replaceAndFindNext=function(){this.editor.getReadOnly()||(this.editor.replace(this.replaceInput.value),this.findNext())},this.replaceAll=function(){this.editor.getReadOnly()||this.editor.replaceAll(this.replaceInput.value)},this.hide=function(){this.element.style.display="none",this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb),this.editor.focus()},this.show=function(e,t){this.element.style.display="",this.replaceBox.style.display=t?"":"none",this.isReplace=t,e&&(this.searchInput.value=e),this.find(!1,!1,!0),this.searchInput.focus(),this.searchInput.select(),this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb)},this.isFocused=function(){var e=document.activeElement;return e==this.searchInput||e==this.replaceInput}}).call(h.prototype),t.SearchBox=h,t.Search=function(e,t){var i=e.searchBox||new h(e);i.show(e.session.getTextRange(),t)}}),function(){ace.acequire(["ace/ext/searchbox"],function(){})}()},function(e,t){ace.define("ace/theme/jsoneditor",["require","exports","module","ace/lib/dom"],function(e,t,i){t.isDark=!1,t.cssClass="ace-jsoneditor",t.cssText='.ace-jsoneditor .ace_gutter { background: #ebebeb; color: #333 } .ace-jsoneditor.ace_editor { font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif; line-height: 1.3; } .ace-jsoneditor .ace_print-margin { width: 1px; background: #e8e8e8 } .ace-jsoneditor .ace_scroller { background-color: #FFFFFF } .ace-jsoneditor .ace_text-layer { color: gray } .ace-jsoneditor .ace_variable { color: #1a1a1a } .ace-jsoneditor .ace_cursor { border-left: 2px solid #000000 } .ace-jsoneditor .ace_overwrite-cursors .ace_cursor { border-left: 0px; border-bottom: 1px solid #000000 } .ace-jsoneditor .ace_marker-layer .ace_selection { background: lightgray } .ace-jsoneditor.ace_multiselect .ace_selection.ace_start { box-shadow: 0 0 3px 0px #FFFFFF; border-radius: 2px } .ace-jsoneditor .ace_marker-layer .ace_step { background: rgb(255, 255, 0) } .ace-jsoneditor .ace_marker-layer .ace_bracket { margin: -1px 0 0 -1px; border: 1px solid #BFBFBF } .ace-jsoneditor .ace_marker-layer .ace_active-line { background: #FFFBD1 } .ace-jsoneditor .ace_gutter-active-line { background-color : #dcdcdc } .ace-jsoneditor .ace_marker-layer .ace_selected-word { border: 1px solid lightgray } .ace-jsoneditor .ace_invisible { color: #BFBFBF } .ace-jsoneditor .ace_keyword, .ace-jsoneditor .ace_meta, .ace-jsoneditor .ace_support.ace_constant.ace_property-value { color: #AF956F } .ace-jsoneditor .ace_keyword.ace_operator { color: #484848 } .ace-jsoneditor .ace_keyword.ace_other.ace_unit { color: #96DC5F } .ace-jsoneditor .ace_constant.ace_language { color: darkorange } .ace-jsoneditor .ace_constant.ace_numeric { color: red } .ace-jsoneditor .ace_constant.ace_character.ace_entity { color: #BF78CC } .ace-jsoneditor .ace_invalid { color: #FFFFFF; background-color: #FF002A; } .ace-jsoneditor .ace_fold { background-color: #AF956F; border-color: #000000 } .ace-jsoneditor .ace_storage, .ace-jsoneditor .ace_support.ace_class, .ace-jsoneditor .ace_support.ace_function, .ace-jsoneditor .ace_support.ace_other, .ace-jsoneditor .ace_support.ace_type { color: #C52727 } .ace-jsoneditor .ace_string { color: green } .ace-jsoneditor .ace_comment { color: #BCC8BA } .ace-jsoneditor .ace_entity.ace_name.ace_tag, .ace-jsoneditor .ace_entity.ace_other.ace_attribute-name { color: #606060 } .ace-jsoneditor .ace_markup.ace_underline { text-decoration: underline } .ace-jsoneditor .ace_indent-guide { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y }';var n=e("../lib/dom");n.importCssString(t.cssText,t.cssClass)})}])}); +//# sourceMappingURL=jsoneditor.map \ No newline at end of file From e2a6c08f19f9ede0abd045b032e168292771407c Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 22 Aug 2016 17:44:22 -0700 Subject: [PATCH 112/134] cleanup prints --- scripts/system/html/js/entityProperties.js | 42 ++++++---------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index bf477a3ed5..7721d06982 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -141,7 +141,6 @@ function createEmitTextPropertyUpdateFunction(propertyName) { return function() { var properties = {}; properties[propertyName] = this.value; - console.log('properties at set thingo yo') EventBridge.emitWebEvent( JSON.stringify({ type: "update", @@ -283,16 +282,13 @@ function setUserDataFromEditor() { var json = null; try { json = editor.get(); - console.log('its good json') } catch (e) { - console.log('failed to parse json', e) alert('Invalid JSON code - look for red X in your code ', +e) } if (json === null) { return; } else { var text = editor.getText() - console.log('editor text at send:', text) EventBridge.emitWebEvent( JSON.stringify({ type: "update", @@ -312,12 +308,9 @@ function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, d var parsedData = {}; try { if ($('#userdata-editor').css('height') === "0px") { - console.log('GET JSON FROM EDITOR') parsedData = editor.getJSON(); } else { - console.log('GET JSON FROM TEXT AREA'); parsedData = JSON.parse(userDataElement.value); - } } catch (e) {} @@ -367,9 +360,6 @@ function createJSONEditor() { }, onError: function(e) { alert('JSON editor:' + e) - }, - onChange: function() { - console.log('editor did change') } }; editor = new JSONEditor(container, options); @@ -412,14 +402,12 @@ function hideUserDataTextArea() { }; function showStaticUserData() { - console.log('showing static userdata') $('#static-userdata').show(); $('#static-userdata').css('height', $('#userdata-editor').height()) $('#static-userdata').text(editor.getText()); }; function removeStaticUserData() { - console.log('hiding static userdata') $('#static-userdata').hide(); }; @@ -432,9 +420,7 @@ function getEditorJSON() { }; function deleteJSONEditor() { - console.log('should delete editor') if (editor !== null) { - console.log('has one so do it') editor.destroy(); } }; @@ -769,20 +755,18 @@ function loaded() { //its json if (Object.keys(json).length === 0 && json.constructor === Object) { //it's an empty object - console.log('empty object') } createJSONEditor(); setEditorJSON(json) showSaveUserDataButton(); hideNewJSONEditorButton(); - console.log('did parse json successfully') } catch (e) { - console.log('error parsing json') + //normal text + elUserData.value = properties.userData; showUserDataTextArea(); hideSaveUserDataButton(); - //normal text } elHyperlinkHref.value = properties.href; @@ -1063,29 +1047,23 @@ function loaded() { elClearUserData.addEventListener("click", function() { deleteJSONEditor(); - console.log('CLEAR USER DATA WAS CLICKED w') elUserData.value = ""; showUserDataTextArea(); - console.log('CLEAR USER DATA WAS CLICKED x') showNewJSONEditorButton(); - console.log('CLEAR USER DATA WAS CLICKED y') hideSaveUserDataButton(); - console.log('CLEAR USER DATA WAS CLICKED z') - var properties = {}; - properties['userData'] = elUserData.value; - console.log('properties at set thingo yo', elUserData.value) - EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: properties, - }) - ); + var properties = {}; + properties['userData'] = elUserData.value; + EventBridge.emitWebEvent( + JSON.stringify({ + type: "update", + properties: properties, + }) + ); }); elSaveUserData.addEventListener("click", function() { - console.log('click on save json button') setUserDataFromEditor(); }); From f7389dc059f12d23a892e467ac1fb46a3b4795f1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Aug 2016 16:28:32 +1200 Subject: [PATCH 113/134] Fix server card window scale --- interface/resources/qml/AddressBarDialog.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index f2bdc5ba6d..8e68906406 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -219,6 +219,7 @@ Window { Window { width: 750; height: 500; + scale: 0.8 // Reset scale of Window to 1.0 (counteract address bar's scale value of 1.25) HifiControls.WebView { anchors.fill: parent; id: storyCardHTML; From d0a25e7783d8ec5773a52a1a30a4cafbb3ead887 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 22 Aug 2016 23:51:35 -0700 Subject: [PATCH 114/134] fix switching entities --- scripts/system/html/entityProperties.html | 3 ++- scripts/system/html/js/entityProperties.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index f5e7ffea63..c39fa00cec 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -67,9 +67,10 @@
+ - +
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 7721d06982..825ae0e72d 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -766,6 +766,7 @@ function loaded() { elUserData.value = properties.userData; showUserDataTextArea(); + showNewJSONEditorButton(); hideSaveUserDataButton(); } From d9a39553bd2321abad94b01a472a3f087afa6d9e Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 00:14:53 -0700 Subject: [PATCH 115/134] style edits and saved message --- scripts/system/html/css/edit-style.css | 6 ++++++ scripts/system/html/css/jsoneditor.css | 2 +- scripts/system/html/entityProperties.html | 2 +- scripts/system/html/js/entityProperties.js | 14 ++++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 58f8833db3..8a6c7786bf 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1096,4 +1096,10 @@ input#reset-to-natural-dimensions { margin-top:5px; margin-bottom:10px; background-color: #2e2e2e; +} + +#userdata-saved{ + margin-top:5px; + font-size:16px; + display:none; } \ No newline at end of file diff --git a/scripts/system/html/css/jsoneditor.css b/scripts/system/html/css/jsoneditor.css index aea0696609..4d63380a62 100644 --- a/scripts/system/html/css/jsoneditor.css +++ b/scripts/system/html/css/jsoneditor.css @@ -212,7 +212,6 @@ div.jsoneditor { position: relative; padding: 0; line-height: 100%; - min-height: 200px; } div.jsoneditor-tree table.jsoneditor-tree { @@ -225,6 +224,7 @@ div.jsoneditor-tree table.jsoneditor-tree { div.jsoneditor-outer { width: 100%; height: 100%; + min-height: 150px; margin: -35px 0 0 0; padding: 0 0 0 0; -moz-box-sizing: border-box; diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index c39fa00cec..0eeb817640 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -70,7 +70,7 @@ - + Saved!
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 825ae0e72d..81c13b63e9 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1064,8 +1064,16 @@ function loaded() { }); + var savedJSONTimer = null; elSaveUserData.addEventListener("click", function() { setUserDataFromEditor(); + $('#userdata-saved').show(); + if (savedJSONTimer !== null) { + clearTimeout(savedJSONTimer); + } + savedJSONTimer = setTimeout(function() { + $('#userdata-saved').hide(); + }, 1500) }); elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); @@ -1080,6 +1088,12 @@ function loaded() { showSaveUserDataButton(); }); + elJSONEditor.addEventListener('mouseenter', function() { + console.log('mouse in the json editor') + }) + elJSONEditor.addEventListener('mouseleave', function() { + console.log('mouse leaves the json editor') + }) var colorChangeFunction = createEmitColorPropertyUpdateFunction( 'color', elColorRed, elColorGreen, elColorBlue); elColorRed.addEventListener('change', colorChangeFunction); From 6ec429fa0bce6eddb02f66e1930e69625daccc18 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 00:19:03 -0700 Subject: [PATCH 116/134] remove unused event listeners --- scripts/system/html/js/entityProperties.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 81c13b63e9..5d6ce8f97e 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1088,12 +1088,6 @@ function loaded() { showSaveUserDataButton(); }); - elJSONEditor.addEventListener('mouseenter', function() { - console.log('mouse in the json editor') - }) - elJSONEditor.addEventListener('mouseleave', function() { - console.log('mouse leaves the json editor') - }) var colorChangeFunction = createEmitColorPropertyUpdateFunction( 'color', elColorRed, elColorGreen, elColorBlue); elColorRed.addEventListener('change', colorChangeFunction); From 7601876641f41f90c28c8cfdb3f38b7664a2175e Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 23 Aug 2016 09:44:28 -0700 Subject: [PATCH 117/134] Scale the activity card back up to match the window being scaled down, so that it covers the address bar. --- interface/resources/qml/AddressBarDialog.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 8e68906406..2536fdade9 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -217,8 +217,8 @@ Window { } Window { - width: 750; - height: 500; + width: 938; + height: 625; scale: 0.8 // Reset scale of Window to 1.0 (counteract address bar's scale value of 1.25) HifiControls.WebView { anchors.fill: parent; From 137f795f2951b083e762daf44cabdd2a3b7276db Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Tue, 23 Aug 2016 11:22:01 -0700 Subject: [PATCH 118/134] Made clara marketplace its own .js --- scripts/defaultScripts.js | 2 +- scripts/system/marketplace.js | 78 ----------------------------------- 2 files changed, 1 insertion(+), 79 deletions(-) delete mode 100644 scripts/system/marketplace.js diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index dc252afcf1..0d76498e84 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -15,7 +15,7 @@ Script.load("system/users.js"); Script.load("system/mute.js"); Script.load("system/goto.js"); Script.load("system/hmd.js"); -Script.load("system/marketplace.js"); +Script.load("system/marketplaces/marketplace.js"); Script.load("system/edit.js"); Script.load("system/mod.js"); Script.load("system/selectAudioDevice.js"); diff --git a/scripts/system/marketplace.js b/scripts/system/marketplace.js deleted file mode 100644 index 01aa4c76ce..0000000000 --- a/scripts/system/marketplace.js +++ /dev/null @@ -1,78 +0,0 @@ -// -// marketplace.js -// -// Created by Eric Levin on 8 Jan 2016 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var toolIconUrl = Script.resolvePath("assets/images/tools/"); -var qml = Script.resolvePath("../../resources/qml/MarketplaceComboBox.qml") - -var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; - -var marketplaceWindow = new OverlayWindow({ - title: "Marketplace", - source: qml, - width: 900, - height: 700, - toolWindow: false, - visible: false, -}); - -var toolHeight = 50; -var toolWidth = 50; -var TOOLBAR_MARGIN_Y = 0; - - -function showMarketplace(marketplaceID) { - var url = MARKETPLACE_URL; - if (marketplaceID) { - url = url + "/items/" + marketplaceID; - } - marketplaceWindow.setVisible(true); - - UserActivityLogger.openedMarketplace(); -} - -function hideMarketplace() { - marketplaceWindow.setVisible(false); -} - -function toggleMarketplace() { - if (marketplaceWindow.visible) { - hideMarketplace(); - } else { - showMarketplace(); - } -} - -var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); - -var browseExamplesButton = toolBar.addButton({ - imageURL: toolIconUrl + "market.svg", - objectName: "marketplace", - buttonState: 1, - defaultState: 1, - hoverState: 3, - alpha: 0.9 -}); - -function onExamplesWindowVisibilityChanged() { - browseExamplesButton.writeProperty('buttonState', marketplaceWindow.visible ? 0 : 1); - browseExamplesButton.writeProperty('defaultState', marketplaceWindow.visible ? 0 : 1); - browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3); -} -function onClick() { - toggleMarketplace(); -} -browseExamplesButton.clicked.connect(onClick); -marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); - -Script.scriptEnding.connect(function () { - toolBar.removeButton("marketplace"); - browseExamplesButton.clicked.disconnect(onClick); - marketplaceWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); -}); From 2d38d47bcca4e88e12714351cc2f8f00375cb6b6 Mon Sep 17 00:00:00 2001 From: elisa-lj11 Date: Tue, 23 Aug 2016 11:24:03 -0700 Subject: [PATCH 119/134] separated clara.js from marketplace.js --- scripts/system/marketplaces/clara.js | 79 ++++++++++++++++++++++ scripts/system/marketplaces/marketplace.js | 77 +++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 scripts/system/marketplaces/clara.js create mode 100644 scripts/system/marketplaces/marketplace.js diff --git a/scripts/system/marketplaces/clara.js b/scripts/system/marketplaces/clara.js new file mode 100644 index 0000000000..7b48f49135 --- /dev/null +++ b/scripts/system/marketplaces/clara.js @@ -0,0 +1,79 @@ +// +// clara.js +// +// Created by Eric Levin on 8 Jan 2016 +// Edited by Elisa Lupin-Jimenez on 23 Aug 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var toolIconUrl = Script.resolvePath("../assets/images/tools/"); +var qml = Script.resolvePath("../../../resources/qml/MarketplaceComboBox.qml") + +var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; + +var marketplaceWindow = new OverlayWindow({ + title: "Marketplace", + source: qml, + width: 900, + height: 700, + toolWindow: false, + visible: false, +}); + +var toolHeight = 50; +var toolWidth = 50; +var TOOLBAR_MARGIN_Y = 0; + + +function showMarketplace(marketplaceID) { + var url = MARKETPLACE_URL; + if (marketplaceID) { + url = url + "/items/" + marketplaceID; + } + marketplaceWindow.setVisible(true); + + UserActivityLogger.openedMarketplace(); +} + +function hideMarketplace() { + marketplaceWindow.setVisible(false); +} + +function toggleMarketplace() { + if (marketplaceWindow.visible) { + hideMarketplace(); + } else { + showMarketplace(); + } +} + +var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + +var browseExamplesButton = toolBar.addButton({ + imageURL: toolIconUrl + "market.svg", + objectName: "marketplace", + buttonState: 1, + defaultState: 1, + hoverState: 3, + alpha: 0.9 +}); + +function onExamplesWindowVisibilityChanged() { + browseExamplesButton.writeProperty('buttonState', marketplaceWindow.visible ? 0 : 1); + browseExamplesButton.writeProperty('defaultState', marketplaceWindow.visible ? 0 : 1); + browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3); +} +function onClick() { + toggleMarketplace(); +} +browseExamplesButton.clicked.connect(onClick); +marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); + +Script.scriptEnding.connect(function () { + toolBar.removeButton("marketplace"); + browseExamplesButton.clicked.disconnect(onClick); + marketplaceWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); +}); diff --git a/scripts/system/marketplaces/marketplace.js b/scripts/system/marketplaces/marketplace.js new file mode 100644 index 0000000000..a43ef6c977 --- /dev/null +++ b/scripts/system/marketplaces/marketplace.js @@ -0,0 +1,77 @@ +// +// marketplace.js +// +// Created by Eric Levin on 8 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var toolIconUrl = Script.resolvePath("../assets/images/tools/"); + +var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; +var marketplaceWindow = new OverlayWebWindow({ + title: "Marketplace", + source: "about:blank", + width: 900, + height: 700, + visible: false +}); + +var toolHeight = 50; +var toolWidth = 50; +var TOOLBAR_MARGIN_Y = 0; + + +function showMarketplace(marketplaceID) { + var url = MARKETPLACE_URL; + if (marketplaceID) { + url = url + "/items/" + marketplaceID; + } + marketplaceWindow.setURL(url); + marketplaceWindow.setVisible(true); + + UserActivityLogger.openedMarketplace(); +} + +function hideMarketplace() { + marketplaceWindow.setVisible(false); + marketplaceWindow.setURL("about:blank"); +} + +function toggleMarketplace() { + if (marketplaceWindow.visible) { + hideMarketplace(); + } else { + showMarketplace(); + } +} + +var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); + +var browseExamplesButton = toolBar.addButton({ + imageURL: toolIconUrl + "market.svg", + objectName: "marketplace", + buttonState: 1, + defaultState: 1, + hoverState: 3, + alpha: 0.9 +}); + +function onExamplesWindowVisibilityChanged() { + browseExamplesButton.writeProperty('buttonState', marketplaceWindow.visible ? 0 : 1); + browseExamplesButton.writeProperty('defaultState', marketplaceWindow.visible ? 0 : 1); + browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3); +} +function onClick() { + toggleMarketplace(); +} +browseExamplesButton.clicked.connect(onClick); +marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); + +Script.scriptEnding.connect(function () { + toolBar.removeButton("marketplace"); + browseExamplesButton.clicked.disconnect(onClick); + marketplaceWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); +}); \ No newline at end of file From 5166a33370fac052f10f277e3b7bd74945eb08f6 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 11:53:20 -0700 Subject: [PATCH 120/134] autosave after 1.5 s no changes --- scripts/system/html/js/entityProperties.js | 39 ++++++++++++++++------ 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 5d6ce8f97e..9f58fbe04d 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -23,6 +23,8 @@ var ICON_FOR_TYPE = { Multiple: "" } +var EDITOR_TIMEOUT_DURATION = 1500; + var colorPickers = []; debugPrint = function(message) { @@ -347,6 +349,7 @@ function setTextareaScrolling(element) { }; var editor = null; +var editorTimeout = null; function createJSONEditor() { var container = document.getElementById("userdata-editor"); @@ -360,6 +363,15 @@ function createJSONEditor() { }, onError: function(e) { alert('JSON editor:' + e) + }, + onChange: function() { + if (editorTimeout !== null) { + clearTimeout(editorTimeout); + } + editorTimeout = setTimeout(function() { + saveJSONUserData(); + }, EDITOR_TIMEOUT_DURATION) + //saveJSONUserData(); } }; editor = new JSONEditor(container, options); @@ -412,7 +424,8 @@ function removeStaticUserData() { }; function setEditorJSON(json) { - return editor.set(json) + editor.set(json) + editor.expandAll(); }; function getEditorJSON() { @@ -425,6 +438,19 @@ function deleteJSONEditor() { } }; +var savedJSONTimer = null; + +function saveJSONUserData() { + setUserDataFromEditor(); + $('#userdata-saved').show(); + if (savedJSONTimer !== null) { + clearTimeout(savedJSONTimer); + } + savedJSONTimer = setTimeout(function() { + $('#userdata-saved').hide(); + }, 1500) +} + function loaded() { openEventBridge(function() { var allSections = []; @@ -1064,16 +1090,9 @@ function loaded() { }); - var savedJSONTimer = null; + elSaveUserData.addEventListener("click", function() { - setUserDataFromEditor(); - $('#userdata-saved').show(); - if (savedJSONTimer !== null) { - clearTimeout(savedJSONTimer); - } - savedJSONTimer = setTimeout(function() { - $('#userdata-saved').hide(); - }, 1500) + saveJSONUserData(); }); elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); From fcf459645d1ea975f1ef04f3aabfb383f8389b46 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 12:02:57 -0700 Subject: [PATCH 121/134] center after teleport --- scripts/system/controllers/teleport.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index 77d0109b9f..f713c0db48 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -564,6 +564,8 @@ function Teleporter() { } }, SMOOTH_ARRIVAL_SPACING); + + HMD.centerUI(); } } From fb6fa687e8d1f46985fc57a17d6c6b5eba57bfe0 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 12:07:59 -0700 Subject: [PATCH 122/134] in the right place... thanks howard! --- scripts/system/controllers/teleport.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index f713c0db48..0aa5820b0f 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -553,6 +553,7 @@ function Teleporter() { _this.smoothArrivalInterval = Script.setInterval(function() { if (_this.arrivalPoints.length === 0) { Script.clearInterval(_this.smoothArrivalInterval); + HMD.centerUI(); return; } var landingPoint = _this.arrivalPoints.shift(); @@ -564,8 +565,8 @@ function Teleporter() { } }, SMOOTH_ARRIVAL_SPACING); - - HMD.centerUI(); + + } } From 477ed8828476f19c6a9687a9460b949316f8409b Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 14:34:28 -0700 Subject: [PATCH 123/134] remove autosave, disable save button until change --- scripts/system/html/entityProperties.html | 4 +-- scripts/system/html/js/entityProperties.js | 42 ++++++++++++++++------ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 0eeb817640..dfa87f86ad 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -67,9 +67,9 @@
- + - + Saved!
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 9f58fbe04d..b9135a1048 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -348,8 +348,11 @@ function setTextareaScrolling(element) { element.setAttribute("scrolling", isScrolling ? "true" : "false"); }; + + var editor = null; var editorTimeout = null; +var lastJSONString=null; function createJSONEditor() { var container = document.getElementById("userdata-editor"); @@ -365,13 +368,15 @@ function createJSONEditor() { alert('JSON editor:' + e) }, onChange: function() { - if (editorTimeout !== null) { - clearTimeout(editorTimeout); + console.log('changed') + if(currentJSONString==='{"":""}'){ + console.log('its empty') + return; } - editorTimeout = setTimeout(function() { - saveJSONUserData(); - }, EDITOR_TIMEOUT_DURATION) - //saveJSONUserData(); + $('#userdata-save').attr('disabled',false) + var currentJSONString = editor.getText(); + + } }; editor = new JSONEditor(container, options); @@ -448,9 +453,18 @@ function saveJSONUserData() { } savedJSONTimer = setTimeout(function() { $('#userdata-saved').hide(); + $('#userdata-save').attr('disabled',true) }, 1500) } +function bindAllNonJSONEditorElements(){ + var inputs = $('input'); + var i; + for(i=0;i Date: Tue, 23 Aug 2016 14:55:46 -0700 Subject: [PATCH 124/134] detect unset skybox --- interface/src/Application.cpp | 2 +- libraries/model/src/model/Skybox.h | 1 + libraries/procedural/src/procedural/Procedural.h | 1 + libraries/procedural/src/procedural/ProceduralSkybox.cpp | 4 ++++ libraries/procedural/src/procedural/ProceduralSkybox.h | 7 ++++--- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ef27f4b9b0..30e2cfd9c6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4326,7 +4326,7 @@ namespace render { } case model::SunSkyStage::SKY_BOX: { auto skybox = skyStage->getSkybox(); - if (skybox) { + if (!skybox->empty()) { PerformanceTimer perfTimer("skybox"); skybox->render(batch, args->getViewFrustum()); break; diff --git a/libraries/model/src/model/Skybox.h b/libraries/model/src/model/Skybox.h index 8c9e7bb1d6..b2e004a2e9 100755 --- a/libraries/model/src/model/Skybox.h +++ b/libraries/model/src/model/Skybox.h @@ -35,6 +35,7 @@ public: void setCubemap(const gpu::TexturePointer& cubemap); const gpu::TexturePointer& getCubemap() const { return _cubemap; } + virtual bool empty() { return _schemaBuffer.get().color == vec3(0) && !_cubemap; } virtual void clear() { setCubemap(nullptr); } void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const; diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index fdca85bbae..c128da0be0 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -38,6 +38,7 @@ public: void parse(const QString& userDataJson); bool ready(); + bool enabled() { return _enabled; } void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation); const gpu::ShaderPointer& getShader() const { return _shader; } diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 843df3aa8d..83122578e7 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -26,6 +26,10 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() { _procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } +bool ProceduralSkybox::empty() { + return !_procedural.enabled() && Skybox::empty(); +} + void ProceduralSkybox::clear() { // Parse and prepare a procedural with no shaders to release textures parse(QString()); diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index b38e481317..30412d559c 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -20,13 +20,14 @@ class ProceduralSkybox: public model::Skybox { public: ProceduralSkybox(); - virtual ~ProceduralSkybox() {}; + ~ProceduralSkybox() override {}; void parse(const QString& userData) { _procedural.parse(userData); } - virtual void clear() override; + bool empty() override; + void clear() override; - virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const override; + void render(gpu::Batch& batch, const ViewFrustum& frustum) const override; static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); protected: From 3abbc98857e88a48393ef164105ed7e035e3bf48 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 15:48:04 -0700 Subject: [PATCH 125/134] save when focus on inputs --- scripts/system/html/js/entityProperties.js | 39 +++++++++++++--------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index b9135a1048..a6cf84b230 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -352,7 +352,7 @@ function setTextareaScrolling(element) { var editor = null; var editorTimeout = null; -var lastJSONString=null; +var lastJSONString = null; function createJSONEditor() { var container = document.getElementById("userdata-editor"); @@ -368,12 +368,10 @@ function createJSONEditor() { alert('JSON editor:' + e) }, onChange: function() { - console.log('changed') - if(currentJSONString==='{"":""}'){ - console.log('its empty') + if (currentJSONString === '{"":""}') { return; } - $('#userdata-save').attr('disabled',false) + $('#userdata-save').attr('disabled', false) var currentJSONString = editor.getText(); @@ -440,6 +438,7 @@ function getEditorJSON() { function deleteJSONEditor() { if (editor !== null) { editor.destroy(); + editor = null; } }; @@ -448,20 +447,29 @@ var savedJSONTimer = null; function saveJSONUserData() { setUserDataFromEditor(); $('#userdata-saved').show(); + $('#userdata-save').attr('disabled', true) if (savedJSONTimer !== null) { clearTimeout(savedJSONTimer); } savedJSONTimer = setTimeout(function() { $('#userdata-saved').hide(); - $('#userdata-save').attr('disabled',true) + }, 1500) } -function bindAllNonJSONEditorElements(){ +function bindAllNonJSONEditorElements() { var inputs = $('input'); var i; - for(i=0;i 1) { + deleteJSONEditor(); var selections = data.selections; var ids = []; @@ -787,7 +800,6 @@ function loaded() { FIXME: See FIXME for property-script-url. elScriptTimestamp.value = properties.scriptTimestamp; */ - //deleteJSONEditor(); hideUserDataTextArea(); var json = null; try { @@ -798,7 +810,6 @@ function loaded() { } if (editor === null) { createJSONEditor(); - console.log('CREATING NEW EDITOR') } setEditorJSON(json); @@ -974,7 +985,7 @@ function loaded() { elLocked.removeAttribute('disabled'); } else { enableProperties(); - elSaveUserData.disabled=true; + elSaveUserData.disabled = true; } var activeElement = document.activeElement; @@ -1115,9 +1126,7 @@ function loaded() { }); elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); - // elJSONEditor.addEventListener('mouseleave',function(){ - // saveJSONUserData(); - // }); + elNewJSONEditor.addEventListener('click', function() { deleteJSONEditor(); createJSONEditor(); @@ -1387,7 +1396,7 @@ function loaded() { clicked = true; }; } - bindMouseLeaveForJSONEditor(); + bindAllNonJSONEditorElements(); }); // Collapsible sections From a5054487ba579fd32c5433d1600ae2473a757060 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 18:18:43 -0700 Subject: [PATCH 126/134] save on no selections, select another entity, etc --- scripts/system/edit.js | 5 +- scripts/system/html/js/entityProperties.js | 89 +++++++++++++++++----- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index a3e5476bf9..51d52367d3 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1427,7 +1427,10 @@ var PropertiesTool = function (opts) { } pushCommandForSelections(); selectionManager._update(); - } else if (data.type === "showMarketplace") { + }else if(data.type==='saveUserData'){ + Entities.editEntity(data.id,data.properties) + } + else if (data.type === "showMarketplace") { showMarketplace(); } else if (data.type === "action") { if (data.action === "moveSelectionToGrid") { diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index a6cf84b230..82706c073d 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -26,7 +26,7 @@ var ICON_FOR_TYPE = { var EDITOR_TIMEOUT_DURATION = 1500; var colorPickers = []; - +var lastEntityID=null; debugPrint = function(message) { EventBridge.emitWebEvent( JSON.stringify({ @@ -84,7 +84,7 @@ function showElements(els, show) { function createEmitCheckedPropertyUpdateFunction(propertyName) { return function() { EventBridge.emitWebEvent( - '{ "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}' + '{"id":' + lastEntityID + ', "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}' ); }; } @@ -106,6 +106,7 @@ function createEmitGroupCheckedPropertyUpdateFunction(group, propertyName) { properties[group][propertyName] = this.checked; EventBridge.emitWebEvent( JSON.stringify({ + id: lastEntityID, type: "update", properties: properties }) @@ -119,7 +120,7 @@ function createEmitNumberPropertyUpdateFunction(propertyName, decimals) { var value = parseFloat(this.value).toFixed(decimals); EventBridge.emitWebEvent( - '{ "type":"update", "properties":{"' + propertyName + '":' + value + '}}' + '{"id":' + lastEntityID + ', "type":"update", "properties":{"' + propertyName + '":' + value + '}}' ); }; } @@ -131,6 +132,7 @@ function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) { properties[group][propertyName] = this.value; EventBridge.emitWebEvent( JSON.stringify({ + id: lastEntityID, type: "update", properties: properties, }) @@ -145,6 +147,7 @@ function createEmitTextPropertyUpdateFunction(propertyName) { properties[propertyName] = this.value; EventBridge.emitWebEvent( JSON.stringify({ + id: lastEntityID, type: "update", properties: properties, }) @@ -159,6 +162,7 @@ function createEmitGroupTextPropertyUpdateFunction(group, propertyName) { properties[group][propertyName] = this.value; EventBridge.emitWebEvent( JSON.stringify({ + id: lastEntityID, type: "update", properties: properties, }) @@ -169,6 +173,7 @@ function createEmitGroupTextPropertyUpdateFunction(group, propertyName) { function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) { return function() { var data = { + id: lastEntityID, type: "update", properties: {} }; @@ -184,6 +189,7 @@ function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) { function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, elZ) { return function() { var data = { + id: lastEntityID, type: "update", properties: {} }; @@ -200,6 +206,7 @@ function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, el function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) { return function() { var data = { + id: lastEntityID, type: "update", properties: {} }; @@ -220,6 +227,7 @@ function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) function emitColorPropertyUpdate(property, red, green, blue, group) { var data = { + id: lastEntityID, type: "update", properties: {} }; @@ -244,6 +252,7 @@ function emitColorPropertyUpdate(property, red, green, blue, group) { function createEmitGroupColorPropertyUpdateFunction(group, property, elRed, elGreen, elBlue) { return function() { var data = { + id: lastEntityID, type: "update", properties: {} }; @@ -273,6 +282,7 @@ function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElemen EventBridge.emitWebEvent( JSON.stringify({ + id: lastEntityID, type: "update", properties: _properties }) @@ -280,7 +290,7 @@ function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElemen } -function setUserDataFromEditor() { +function setUserDataFromEditor(noUpdate) { var json = null; try { json = editor.get(); @@ -291,20 +301,35 @@ function setUserDataFromEditor() { return; } else { var text = editor.getText() - EventBridge.emitWebEvent( - JSON.stringify({ - type: "update", - properties: { - userData: text - }, - }) - ); + console.log('saving as text:', text) + if (noUpdate === true) { + EventBridge.emitWebEvent( + JSON.stringify({ + id: lastEntityID, + type: "saveUserData", + properties: { + userData: text + }, + }) + ); + return; + } else { + EventBridge.emitWebEvent( + JSON.stringify({ + id: lastEntityID, + type: "update", + properties: { + userData: text + }, + }) + ); + } + } } - function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, defaultValue) { var properties = {}; var parsedData = {}; @@ -337,6 +362,7 @@ function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, d EventBridge.emitWebEvent( JSON.stringify({ + id: lastEntityID, type: "update", properties: properties, }) @@ -368,11 +394,12 @@ function createJSONEditor() { alert('JSON editor:' + e) }, onChange: function() { + var currentJSONString = editor.getText(); + if (currentJSONString === '{"":""}') { return; } $('#userdata-save').attr('disabled', false) - var currentJSONString = editor.getText(); } @@ -444,8 +471,9 @@ function deleteJSONEditor() { var savedJSONTimer = null; -function saveJSONUserData() { - setUserDataFromEditor(); +function saveJSONUserData(noUpdate) { + console.log('start saving userdata') + setUserDataFromEditor(noUpdate); $('#userdata-saved').show(); $('#userdata-save').attr('disabled', true) if (savedJSONTimer !== null) { @@ -453,7 +481,7 @@ function saveJSONUserData() { } savedJSONTimer = setTimeout(function() { $('#userdata-saved').hide(); - + }, 1500) } @@ -467,12 +495,23 @@ function bindAllNonJSONEditorElements() { if (e.target.id === "userdata-new-editor" || e.target.id === "userdata-clear") { return; } else { - saveJSONUserData(); + console.log('save on focus',e) + saveJSONUserData(true); } }) } } +function unbindAllInputs() { + var inputs = $('input'); + var i; + for (i = 0; i < inputs.length; i++) { + var input = inputs[i]; + var field = $(input); + field.unbind(); + } +} + function loaded() { openEventBridge(function() { var allSections = []; @@ -667,7 +706,9 @@ function loaded() { if (data.type == "update") { if (data.selections.length == 0) { - if (editor !== null) { + if (editor !== null && lastEntityID!==null) { + console.log('save on no selections') + saveJSONUserData(true); deleteJSONEditor(); } elTypeIcon.style.display = "none"; @@ -707,9 +748,13 @@ function loaded() { disableProperties(); } else { - properties = data.selections[0].properties; + if (lastEntityID !== properties.id && lastEntityID!==null) { + console.log('save on init') + saveJSONUserData(true); + } + lastEntityID = properties.id; elID.innerHTML = properties.id; elType.innerHTML = properties.type; @@ -1112,6 +1157,7 @@ function loaded() { properties['userData'] = elUserData.value; EventBridge.emitWebEvent( JSON.stringify({ + id: lastEntityID, type: "update", properties: properties, }) @@ -1122,7 +1168,8 @@ function loaded() { elSaveUserData.addEventListener("click", function() { - saveJSONUserData(); + console.log('save on click') + saveJSONUserData(true); }); elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); From 2f4617cd5e3cec5239ca58f26fddb2469e35a200 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 18:20:33 -0700 Subject: [PATCH 127/134] quiet some prints --- scripts/system/edit.js | 11 +++++------ scripts/system/html/js/entityProperties.js | 8 +------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 51d52367d3..964fc0306f 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -143,7 +143,7 @@ function showMarketplace(marketplaceID) { if (marketplaceID) { url = url + "/items/" + marketplaceID; } - print("setting marketplace URL to " + url); + // print("setting marketplace URL to " + url); marketplaceWindow.setURL(url); marketplaceWindow.setVisible(true); marketplaceWindow.raise(); @@ -216,7 +216,6 @@ var toolBar = (function () { } function initialize() { - print("QQQ creating edit toolbar"); Script.scriptEnding.connect(cleanup); Window.domainChanged.connect(function () { @@ -794,7 +793,7 @@ var modelMenuAddedDelete = false; var originalLightsArePickable = Entities.getLightsArePickable(); function setupModelMenus() { - print("setupModelMenus()"); + // print("setupModelMenus()"); // adj our menuitems Menu.addMenuItem({ menuName: "Edit", @@ -803,7 +802,7 @@ function setupModelMenus() { grouping: "Advanced" }); if (!Menu.menuItemExists("Edit", "Delete")) { - print("no delete... adding ours"); + // print("no delete... adding ours"); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", @@ -815,7 +814,7 @@ function setupModelMenus() { }); modelMenuAddedDelete = true; } else { - print("delete exists... don't add ours"); + // print("delete exists... don't add ours"); } Menu.addMenuItem({ @@ -1047,7 +1046,7 @@ function deleteSelectedEntities() { SelectionManager.clearSelections(); pushCommandForSelections([], savedProperties); } else { - print(" Delete Entity.... not holding..."); + // print(" Delete Entity.... not holding..."); } } diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 82706c073d..5ad228af1b 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -301,7 +301,6 @@ function setUserDataFromEditor(noUpdate) { return; } else { var text = editor.getText() - console.log('saving as text:', text) if (noUpdate === true) { EventBridge.emitWebEvent( JSON.stringify({ @@ -472,7 +471,6 @@ function deleteJSONEditor() { var savedJSONTimer = null; function saveJSONUserData(noUpdate) { - console.log('start saving userdata') setUserDataFromEditor(noUpdate); $('#userdata-saved').show(); $('#userdata-save').attr('disabled', true) @@ -495,7 +493,6 @@ function bindAllNonJSONEditorElements() { if (e.target.id === "userdata-new-editor" || e.target.id === "userdata-clear") { return; } else { - console.log('save on focus',e) saveJSONUserData(true); } }) @@ -707,7 +704,6 @@ function loaded() { if (data.selections.length == 0) { if (editor !== null && lastEntityID!==null) { - console.log('save on no selections') saveJSONUserData(true); deleteJSONEditor(); } @@ -749,8 +745,7 @@ function loaded() { } else { properties = data.selections[0].properties; - if (lastEntityID !== properties.id && lastEntityID!==null) { - console.log('save on init') + if (lastEntityID !== properties.id && lastEntityID!==null && editor!==null) { saveJSONUserData(true); } @@ -1168,7 +1163,6 @@ function loaded() { elSaveUserData.addEventListener("click", function() { - console.log('save on click') saveJSONUserData(true); }); From c4c6b30440db678e9f1a1787fb9f19a961ee5bc0 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 12:02:57 -0700 Subject: [PATCH 128/134] center after teleport --- scripts/system/controllers/teleport.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index 77d0109b9f..f713c0db48 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -564,6 +564,8 @@ function Teleporter() { } }, SMOOTH_ARRIVAL_SPACING); + + HMD.centerUI(); } } From 48bab49210c69cff1f9d86a1e13d4e0dc731de3f Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 23 Aug 2016 12:07:59 -0700 Subject: [PATCH 129/134] in the right place... thanks howard! --- scripts/system/controllers/teleport.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index f713c0db48..0aa5820b0f 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -553,6 +553,7 @@ function Teleporter() { _this.smoothArrivalInterval = Script.setInterval(function() { if (_this.arrivalPoints.length === 0) { Script.clearInterval(_this.smoothArrivalInterval); + HMD.centerUI(); return; } var landingPoint = _this.arrivalPoints.shift(); @@ -564,8 +565,8 @@ function Teleporter() { } }, SMOOTH_ARRIVAL_SPACING); - - HMD.centerUI(); + + } } From 6c99a330093807f25e85e7204373f191925155c1 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 23 Aug 2016 14:55:46 -0700 Subject: [PATCH 130/134] detect unset skybox --- interface/src/Application.cpp | 2 +- libraries/model/src/model/Skybox.h | 1 + libraries/procedural/src/procedural/Procedural.h | 1 + libraries/procedural/src/procedural/ProceduralSkybox.cpp | 4 ++++ libraries/procedural/src/procedural/ProceduralSkybox.h | 7 ++++--- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 836b48b3fb..6b4eb8d140 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4306,7 +4306,7 @@ namespace render { } case model::SunSkyStage::SKY_BOX: { auto skybox = skyStage->getSkybox(); - if (skybox) { + if (!skybox->empty()) { PerformanceTimer perfTimer("skybox"); skybox->render(batch, args->getViewFrustum()); break; diff --git a/libraries/model/src/model/Skybox.h b/libraries/model/src/model/Skybox.h index 8c9e7bb1d6..b2e004a2e9 100755 --- a/libraries/model/src/model/Skybox.h +++ b/libraries/model/src/model/Skybox.h @@ -35,6 +35,7 @@ public: void setCubemap(const gpu::TexturePointer& cubemap); const gpu::TexturePointer& getCubemap() const { return _cubemap; } + virtual bool empty() { return _schemaBuffer.get().color == vec3(0) && !_cubemap; } virtual void clear() { setCubemap(nullptr); } void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const; diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index fdca85bbae..c128da0be0 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -38,6 +38,7 @@ public: void parse(const QString& userDataJson); bool ready(); + bool enabled() { return _enabled; } void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation); const gpu::ShaderPointer& getShader() const { return _shader; } diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 843df3aa8d..83122578e7 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -26,6 +26,10 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() { _procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } +bool ProceduralSkybox::empty() { + return !_procedural.enabled() && Skybox::empty(); +} + void ProceduralSkybox::clear() { // Parse and prepare a procedural with no shaders to release textures parse(QString()); diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index b38e481317..30412d559c 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -20,13 +20,14 @@ class ProceduralSkybox: public model::Skybox { public: ProceduralSkybox(); - virtual ~ProceduralSkybox() {}; + ~ProceduralSkybox() override {}; void parse(const QString& userData) { _procedural.parse(userData); } - virtual void clear() override; + bool empty() override; + void clear() override; - virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const override; + void render(gpu::Batch& batch, const ViewFrustum& frustum) const override; static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); protected: From 45e3f926a1c417654df4eaf683fa2f3562a6c992 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 24 Aug 2016 14:19:27 -0700 Subject: [PATCH 131/134] removed unused prints and cleanup --- scripts/system/edit.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 964fc0306f..d34d4acffc 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -143,7 +143,6 @@ function showMarketplace(marketplaceID) { if (marketplaceID) { url = url + "/items/" + marketplaceID; } - // print("setting marketplace URL to " + url); marketplaceWindow.setURL(url); marketplaceWindow.setVisible(true); marketplaceWindow.raise(); @@ -793,7 +792,6 @@ var modelMenuAddedDelete = false; var originalLightsArePickable = Entities.getLightsArePickable(); function setupModelMenus() { - // print("setupModelMenus()"); // adj our menuitems Menu.addMenuItem({ menuName: "Edit", @@ -802,7 +800,6 @@ function setupModelMenus() { grouping: "Advanced" }); if (!Menu.menuItemExists("Edit", "Delete")) { - // print("no delete... adding ours"); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", @@ -813,8 +810,6 @@ function setupModelMenus() { grouping: "Advanced" }); modelMenuAddedDelete = true; - } else { - // print("delete exists... don't add ours"); } Menu.addMenuItem({ @@ -1045,8 +1040,6 @@ function deleteSelectedEntities() { } SelectionManager.clearSelections(); pushCommandForSelections([], savedProperties); - } else { - // print(" Delete Entity.... not holding..."); } } @@ -1162,7 +1155,6 @@ function getPositionToImportEntity() { return position; } function importSVO(importURL) { - print("Import URL requested: " + importURL); if (!Entities.canAdjustLocks()) { Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); return; @@ -1426,10 +1418,9 @@ var PropertiesTool = function (opts) { } pushCommandForSelections(); selectionManager._update(); - }else if(data.type==='saveUserData'){ - Entities.editEntity(data.id,data.properties) - } - else if (data.type === "showMarketplace") { + } else if(data.type === 'saveUserData'){ + Entities.editEntity(data.id, data.properties) + } else if (data.type === "showMarketplace") { showMarketplace(); } else if (data.type === "action") { if (data.action === "moveSelectionToGrid") { From 384c3dd5438c1e7466019ebb04ec6a4280420be4 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 24 Aug 2016 14:49:41 -0700 Subject: [PATCH 132/134] cleanup and handle a bug when changing from normal text userdata to another field --- scripts/system/html/js/entityProperties.js | 26 +++++++++------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 5ad228af1b..a20906fe34 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -26,7 +26,7 @@ var ICON_FOR_TYPE = { var EDITOR_TIMEOUT_DURATION = 1500; var colorPickers = []; -var lastEntityID=null; +var lastEntityID = null; debugPrint = function(message) { EventBridge.emitWebEvent( JSON.stringify({ @@ -333,11 +333,7 @@ function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, d var properties = {}; var parsedData = {}; try { - if ($('#userdata-editor').css('height') === "0px") { - parsedData = editor.getJSON(); - } else { - parsedData = JSON.parse(userDataElement.value); - } + parsedData = JSON.parse(userDataElement.value); } catch (e) {} if (!(groupName in parsedData)) { @@ -393,7 +389,7 @@ function createJSONEditor() { alert('JSON editor:' + e) }, onChange: function() { - var currentJSONString = editor.getText(); + var currentJSONString = editor.getText(); if (currentJSONString === '{"":""}') { return; @@ -493,7 +489,10 @@ function bindAllNonJSONEditorElements() { if (e.target.id === "userdata-new-editor" || e.target.id === "userdata-clear") { return; } else { - saveJSONUserData(true); + if ($('#userdata-editor').css('height') !== "0px") { + saveJSONUserData(true); + + } } }) } @@ -703,7 +702,7 @@ function loaded() { if (data.type == "update") { if (data.selections.length == 0) { - if (editor !== null && lastEntityID!==null) { + if (editor !== null && lastEntityID !== null) { saveJSONUserData(true); deleteJSONEditor(); } @@ -745,7 +744,7 @@ function loaded() { } else { properties = data.selections[0].properties; - if (lastEntityID !== properties.id && lastEntityID!==null && editor!==null) { + if (lastEntityID !== properties.id && lastEntityID !== null && editor !== null) { saveJSONUserData(true); } @@ -843,11 +842,8 @@ function loaded() { hideUserDataTextArea(); var json = null; try { - json = JSON.parse(properties.userData) - //its json - if (Object.keys(json).length === 0 && json.constructor === Object) { - //it's an empty object - } + json = JSON.parse(properties.userData); + if (editor === null) { createJSONEditor(); } From 5305ec7febd9e418a9ed9ccab9802c356742687c Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 24 Aug 2016 14:51:15 -0700 Subject: [PATCH 133/134] html beautify --- scripts/system/html/entityProperties.html | 1112 ++++++++++----------- 1 file changed, 539 insertions(+), 573 deletions(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index dfa87f86ad..26c7f53997 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -7,588 +7,554 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html --> - - - Properties - - - - - - - - - - - - - - -
-
-
- -
-
- - -
-
- - -
-
-
- -
- - -
-
- - -
- -
- -
-
- - - - Saved! -
-
-
- -
-
- - -
- - - - - - -
- M -
-
- -
-
-
-
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
-
-
-
- -
- - - -
-
-
-
- - -
-
- - -
-
-
-
- -
-
-
- - -
-
-
-
-
- -
-
-
-
-
-
- -
- - -
-
- - -
-
- - -
- - -
- M -
-
- -
-
-
-
-
-
-
- - -
-
-
- -
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- - -
- M -
-
- - -
-
- - -
- -
-
-
- Collides With + + Properties + + + + + + + + + + + + + +
+
+
+
-
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
-
- Grabbing -
-
-
- - -
- -
- - -
- -
- - -
-
-
- -
- -
-
- - -
-
- - -
-
-
- - - -
- - -
- M -
-
- - -
- -
- - -
-
-
- - -
- -
-
- - + +
-
- - -
-
- - -
-
- - +
+ +
-
-
- - +
+ +
+ + +
+
+ + +
+ +
+ +
+
+ + + + Saved! +
+
+
+ +
+
+ + +
+ + +
+ M +
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+ + + +
+
+
+
+ +
- - + +
-
- - +
+
+
+ +
+
+
+ + +
+
+
+
+
+ +
+
+
+
+
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ M +
+
+ +
+
+
+
+
+
+
+ + +
+
+
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ M +
+
+ + +
+
+ + +
+
+
+
+ Collides With +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ Grabbing +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+ + +
+
+ + +
+
+
+ + + +
+
+ M +
+
+ + +
+ +
+ + +
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ + +
+
+ + +
+
+ M +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ M +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+
+ +
+
+
+
+
+
+
+ + +
+
+ M +
+
+ + +
+
+ M +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
-
-
- - -
-
- - -
- -
- M -
-
- - -
-
- - -
-
- - -
-
-
- -
-
-
-
-
-
-
-
- -
-
-
-
-
-
- - -
- M -
-
- - -
-
- - -
-
- - -
- -
- -
-
-
- -
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
- - -
-
- - -
- -
- -
-
-
-
-
-
-
-
-
- - -
- -
-
-
-
-
-
-
- -
- -
- - -
- -
-
-
- -
-
-
-
-
-
-
- - -
- - -
- M -
-
- - -
- - -
- M -
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
- - + + \ No newline at end of file From af2fb5d7ed4f816d4755cfba4ace8a9c661411e5 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 24 Aug 2016 14:54:00 -0700 Subject: [PATCH 134/134] beautify more html --- scripts/system/html/entityList.html | 112 +++++++++++++------------- scripts/system/html/gridControls.html | 112 ++++++++++++-------------- 2 files changed, 107 insertions(+), 117 deletions(-) diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index 2088898613..b19a55b5a2 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -7,73 +7,71 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html --> - - - - - - - - - - -
- -
- - -
- - -
- -
-
- Y -
- - + + + + + + + + + +
+ +
+ +
+ +
-
- - +
+
+ Y +
+ + +
+
+
+
+ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - -
TypeNameFile
TypeName
URL
??
TypeNameFile
TypeName
URL
??
-
- No entities found within a 100 meter radius. Try moving to a different location and refreshing. + + +
+ No entities found within a 100 meter radius. Try moving to a different location and refreshing. +
-
- - + + \ No newline at end of file diff --git a/scripts/system/html/gridControls.html b/scripts/system/html/gridControls.html index f7f206d702..cd646fed51 100644 --- a/scripts/system/html/gridControls.html +++ b/scripts/system/html/gridControls.html @@ -7,67 +7,59 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html --> - - - - - - - - - - - - -
- -
- -
- -
- - -
- -
- - -
- -
-
- - + + + + + + + + + + + +
+
+
-
- - +
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ +
+
+
+
+
+
+
+ + + +
- -
- - -
- -
-
- -
-
-
-
-
-
- -
- - - - -
-
- - + + \ No newline at end of file