diff options
Diffstat (limited to 'plugins/SegmentEditor/javascripts/Segmentation.js')
-rw-r--r-- | plugins/SegmentEditor/javascripts/Segmentation.js | 516 |
1 files changed, 22 insertions, 494 deletions
diff --git a/plugins/SegmentEditor/javascripts/Segmentation.js b/plugins/SegmentEditor/javascripts/Segmentation.js index 0153a6b491..e018fec7cd 100644 --- a/plugins/SegmentEditor/javascripts/Segmentation.js +++ b/plugins/SegmentEditor/javascripts/Segmentation.js @@ -19,11 +19,6 @@ Segmentation = (function($) { $('.segmentListContainer .segmentationContainer .title').trigger('click').focus(); }); - function preselectFirstMetricMatch(rowNode) - { - var matchValue = $(rowNode).find('.metricMatchBlock option:first').attr('value'); - $(rowNode).find('.metricMatchBlock select').val(matchValue); - } var segmentation = function segmentation(config) { if (!config.target) { @@ -128,98 +123,11 @@ Segmentation = (function($) { } }; - var getAndDiv = function(){ - if(typeof andDiv === "undefined"){ - var andDiv = self.editorTemplate.find("> div.segment-and").clone(); - } - return andDiv.clone(); - }; - - var getOrDiv = function(){ - if(typeof orDiv === "undefined"){ - var orDiv = self.editorTemplate.find("> div.segment-or").clone(); - } - return orDiv.clone(); - }; - - var getMockedInputSet = function(){ - var mockedInputSet = self.editorTemplate.find("div.segment-row-inputs").clone(); - var clonedInput = mockedInputSet.clone(); - preselectFirstMetricMatch(clonedInput); - - return clonedInput; - }; - - var getMockedInputRowHtml = function(){ - return '<div class="segment-row"><a class="segment-close" href="#"></a><div class="segment-row-inputs">'+getMockedInputSet().html()+'</div></div>'; - }; - - var getMockedFormRow = function(){ - var mockedFormRow = self.editorTemplate.find("div.segment-rows").clone(); - $(mockedFormRow).find(".segment-row").append(getMockedInputSet()).after(getAddOrBlockButtonHtml).after(getOrDiv()); - var clonedRow = mockedFormRow.clone(); - preselectFirstMetricMatch(clonedRow); - - return clonedRow; - }; - - var getInitialStateRowsHtml = function(){ - if(typeof initialStateRows === "undefined"){ - var content = self.editorTemplate.find("div.initial-state-rows").html(); - var initialStateRows = $(content).clone(); - } - return initialStateRows; - }; - - var revokeInitialStateRows = function(){ - $(self.form).find(".segment-add-row").remove(); - $(self.form).find(".segment-and").remove(); - }; - - var appendSpecifiedRowHtml= function(metric) { - var mockedRow = getMockedFormRow(); - $(self.form).find(".segment-content > h3").after(mockedRow); - $(self.form).find(".segment-content").append(getAndDiv()); - $(self.form).find(".segment-content").append(getAddNewBlockButtonHtml()); - doDragDropBindings(); - $(self.form).find(".metricList").val(metric).trigger("change"); - preselectFirstMetricMatch(mockedRow); - }; - - var appendComplexRowHtml = function(block){ - var key; - var newRow = getMockedFormRow(); - - var x = $(newRow).find(".metricMatchBlock select"); - $(newRow).find(".metricListBlock select").val(block[0].metric); - $(newRow).find(".metricMatchBlock select").val(block[0].match); - $(newRow).find(".metricValueBlock input").val(block[0].value); - - if(block.length > 1) { - $(newRow).find(".segment-add-or").remove(); - for(key = 1; key < block.length;key++) { - var newSubRow = $(getMockedInputRowHtml()).clone(); - $(newSubRow).find(".metricListBlock select").val(block[key].metric); - $(newSubRow).find(".metricMatchBlock select").val(block[key].match); - $(newSubRow).find(".metricValueBlock input").val(block[key].value); - $(newRow).append(newSubRow).append(getOrDiv()); - } - $(newRow).append(getAddOrBlockButtonHtml()); - } - $(self.form).find(".segment-content").append(newRow).append(getAndDiv()); - }; - - var applyInitialStateModification = function(){ - $(self.form).find(".segment-add-row").remove(); - $(self.form).find(".segment-content").append(getInitialStateRowsHtml()); - doDragDropBindings(); - }; - var getSegmentFromId = function (id) { if(self.availableSegments.length > 0) { for(var i = 0; i < self.availableSegments.length; i++) { - segment = self.availableSegments[i]; + var segment = self.availableSegments[i]; if(segment.idsegment == id) { return segment; } @@ -361,7 +269,7 @@ Segmentation = (function($) { newOption = '<option data-idsegment="'+segment.idsegment+'" data-definition="'+(segment.definition).replace(/"/g, '"')+'" title="'+getSegmentTooltipEnrichedWithUsername(segment)+'">'+getSegmentName(segment)+'</option>'; segmentsDropdown.append(newOption); } - $(html).find(".segment-content > h3").after(getInitialStateRowsHtml()).show(); + $(html).find(".segment-content > h3").after('<div piwik-segment-generator add-initial-condition="true"></div>').show(); return html; }; @@ -372,62 +280,6 @@ Segmentation = (function($) { }); }; - var findAndExplodeByMatch = function(metric){ - var matches = ["==" , "!=" , "<=", ">=", "=@" , "!@","<",">", "=^", "=$"]; - var newMetric = {}; - var minPos = metric.length; - var match, index; - var singleChar = false; - - for(var key=0; key < matches.length; key++) - { - match = matches[key]; - index = metric.indexOf(match); - if( index != -1){ - if(index < minPos){ - minPos = index; - if(match.length == 1){ - singleChar = true; - } - } - } - } - - if(minPos < metric.length){ - // sth found - explode - if(singleChar == true){ - newMetric.metric = metric.substr(0,minPos); - newMetric.match = metric.substr(minPos,1); - newMetric.value = metric.substr(minPos+1); - } else { - newMetric.metric = metric.substr(0,minPos); - newMetric.match = metric.substr(minPos,2); - newMetric.value = metric.substr(minPos+2); - } - // if value is only "" -> change to empty string - if(newMetric.value == '""') - { - newMetric.value = ""; - } - } - - newMetric.value = decodeURIComponent(newMetric.value); - return newMetric; - }; - - var parseSegmentStr = function(segmentStr) - { - var blocks; - blocks = segmentStr.split(";"); - for(var key in blocks){ - blocks[key] = blocks[key].split(","); - for(var innerkey = 0; innerkey < blocks[key].length; innerkey++){ - blocks[key][innerkey] = findAndExplodeByMatch(blocks[key][innerkey]); - } - } - return blocks; - }; - var openEditForm = function(segment){ addForm("edit", segment); @@ -441,24 +293,14 @@ Segmentation = (function($) { .html( getSegmentName(segment) ) .prop( 'title', getSegmentTooltipEnrichedWithUsername(segment)); - if(segment.definition != ""){ - revokeInitialStateRows(); - var blocks = parseSegmentStr(segment.definition); - for(var key in blocks){ - appendComplexRowHtml(blocks[key]); - } - $(self.form).find(".segment-content").append(getAddNewBlockButtonHtml()); - } $(self.form).find(".metricList").each( function(){ $(this).trigger("change", true); }); - doDragDropBindings(); }; var displayFormAddNewSegment = function (e) { closeAllOpenLists(); addForm("new"); - doDragDropBindings(); }; var filterSegmentList = function (keyword) { @@ -561,17 +403,6 @@ Segmentation = (function($) { displayFormAddNewSegment(e); }); - self.target.on('change', "select.metricList", function (e, persist) { - if (typeof persist === "undefined") { - persist = false; - } - alterMatchesList(this, true); - - doDragDropBindings(); - - autoSuggestValues(this, persist); - }); - // attach event that will clear segment list filtering input after clicking x self.target.on('click', ".segmentFilterContainer span", function (e) { $(e.target).parent().find(".segmentFilter").val(self.translations['General_Search']).trigger('keyup'); @@ -613,8 +444,10 @@ Segmentation = (function($) { // self.target.on('click', "a.editSegmentName", function (e) { - var oldName = $(e.currentTarget).parents("h3").find("span").text(); - $(e.currentTarget).parents("h3").find("span").hide(); + var $h3 = $(e.currentTarget).parents("h3"); + $h3.css({'margin': '0 0 0 6px'}); + var oldName = $h3.find("span").text(); + $h3.find("span").hide(); $(e.currentTarget).hide(); $(e.currentTarget).before('<input class="edit_segment_name" type="text"/>'); $(e.currentTarget).siblings(".edit_segment_name").focus().val(oldName); @@ -645,48 +478,6 @@ Segmentation = (function($) { openEditFormGivenSegment(option); }); - // attach event that shows/hides child elements of each metric category - self.target.on('click', '.segment-nav a.metric_category', function (e) { - $(e.currentTarget).siblings("ul").toggle(); - }); - - self.target.on('click', ".custom_select_search a", function (e) { - $(self.form).find(".segmentSearch").val("").trigger("keyup").val(self.translations['General_Search']); - }); - - // attach event that will clear search input upon focus if its content is default - self.target.on('focus', '.segmentSearch', function (e) { - var search = $(e.currentTarget).val(); - if(search == self.translations['General_Search']) - $(e.currentTarget).val(""); - }); - - // attach event that will set search input value upon blur if its content is not null - self.target.on('blur', '.segmentSearch', function (e) { - var search = $(e.currentTarget).val(); - if(search == ""){ - clearSearchMetricHighlight(); - $(e.currentTarget).val(self.translations['General_Search']); - } - }); - - // bind search action triggering - only when input text is longer than 2 chars - self.target.on('keyup', '.segmentSearch', function (e) { - var search = $(e.currentTarget).val(); - if( search.length >= 2) - { - clearTimeout(self.timer); - self.searchAllowed = true; - self.timer = setTimeout(function(){ - searchSegments(search); - }, 500); - } - else{ - self.searchAllowed = false; - clearSearchMetricHighlight(); - } - }); - self.target.on('click', ".delete", function() { var segmentName = $(self.form).find(".segment-content > h3 > span").text(); var segmentId = $(self.form).find(".available_segments_select option:selected").attr("data-idsegment"); @@ -709,7 +500,10 @@ Segmentation = (function($) { }); $("body").on("keyup", function (e) { - if(e.keyCode == "27"){ + if(e.keyCode == "27" || e.which === 27) { + if (self.target.find('[uicontrol="expandable-select"] .expandableList:visible').length) { + return; + } $(".segmentListContainer", self.target).show(); closeForm(); } @@ -719,146 +513,6 @@ Segmentation = (function($) { // segment manipulation events // - // upon clicking - add new segment block, then bind 'x' action to newly added row - self.target.on('click', ".segment-add-row a", function(event, data){ - var mockedRow = getMockedFormRow(); - $(self.form).find(".segment-and:last").after(getAndDiv()).after(mockedRow); - if(typeof data !== "undefined"){ - $(self.form).find(".metricList:last").val(data); - } - $(self.form).find(".metricList:last").trigger('change'); - preselectFirstMetricMatch(mockedRow); - doDragDropBindings(); - }); - - self.target.on("click", ".segment-add-row span", function(event, data){ - if(typeof data !== "undefined") { - var mockedRow = getMockedFormRow(); - $(self.form).find(".segment-and:last").after(getAndDiv()).after(mockedRow); - preselectFirstMetricMatch(mockedRow); - $(self.form).find(".metricList:last").val(data).trigger('change'); - doDragDropBindings(); - } - }); - - // add new OR block - self.target.on("click", ".segment-add-or a", function(event, data){ - var parentRows = $(event.currentTarget).parents(".segment-rows"); - - parentRows.find(".segment-or:last").after(getOrDiv()).after(getMockedInputRowHtml()); - if(typeof data !== "undefined"){ - parentRows.find(".metricList:last").val(data); - } - parentRows.find(".metricList:last").trigger('change'); - - var addedRow = parentRows.find('.segment-row:last'); - preselectFirstMetricMatch(addedRow); - doDragDropBindings(); - }); - - self.target.on("click", ".segment-close", function (e) { - var target = e.currentTarget; - var rowCnt = $(target).parents(".segment-rows").find(".segment-row").length; - var globalRowCnt = $(self.form).find(".segment-close").length; - if(rowCnt > 1){ - $(target).parents(".segment-row").next().remove(); - $(target).parents(".segment-row").remove(); - } - else if(rowCnt == 1){ - $(target).parents(".segment-rows").next().remove(); - $(target).parents(".segment-rows").remove(); - if(globalRowCnt == 1){ - applyInitialStateModification(); - } - } - }); - }; - - // Request auto-suggest values - var autoSuggestValues = function(select, persist) { - var type = $(select).find("option:selected").attr("value"); - if(!persist) { - var parents = $(select).parents('.segment-row'); - var loadingElement = parents.find(".segment-loading"); - loadingElement.show(); - var inputElement = parents.find(".metricValueBlock input"); - var segmentName = $('option:selected',select).attr('value'); - - var ajaxHandler = new ajaxHelper(); - ajaxHandler.addParams({ - module: 'API', - format: 'json', - method: 'API.getSuggestedValuesForSegment', - segmentName: segmentName - }, 'GET'); - ajaxHandler.useRegularCallbackInCaseOfError = true; - ajaxHandler.setTimeout(20000); - ajaxHandler.setErrorCallback(function(response) { - loadingElement.hide(); - inputElement.autocomplete({ - source: [], - minLength: 0 - }); - $(inputElement).autocomplete('search', $(inputElement).val()); - }); - ajaxHandler.setCallback(function(response) { - loadingElement.hide(); - - if (response && response.result != 'error') { - - inputElement.autocomplete({ - source: response, - minLength: 0, - select: function(event, ui){ - event.preventDefault(); - $(inputElement).val(ui.item.value); - } - }); - } - - inputElement.click(function (e) { - $(inputElement).autocomplete('search', $(inputElement).val()); - }); - }); - ajaxHandler.send(); - } - }; - - var alterMatchesList = function(select, persist){ - var oldMatch; - var type = $(select).find("option:selected").attr("data-type"); - var matchSelector = $(select).parents(".segment-input").siblings(".metricMatchBlock").find("select"); - if(persist === true){ - oldMatch = matchSelector.find("option:selected").val(); - } else { - oldMatch = ""; - } - - if(type === "dimension" || type === "metric"){ - matchSelector.empty(); - var optionsHtml = ""; - for(var key in self.availableMatches[type]){ - optionsHtml += '<option value="'+key+'">'+self.availableMatches[type][key]+'</option>'; - } - } - - matchSelector.append(optionsHtml); - - if (matchSelector.find('option[value="' + oldMatch + '"]').length) { - matchSelector.val(oldMatch); - } else { - preselectFirstMetricMatch(matchSelector.parent()); - } - }; - - var getAddNewBlockButtonHtml = function() - { - if(typeof addNewBlockButton === "undefined") - { - var addNewBlockButton = self.editorTemplate.find("> div.segment-add-row").clone(); - } - return addNewBlockButton.clone(); - }; var getAddOrBlockButtonHtml = function(){ @@ -868,16 +522,6 @@ Segmentation = (function($) { return addOrBlockButton.clone(); }; - var placeSegmentationFormControls = function(){ - doDragDropBindings(); - $(self.form).find(".scrollable").jScrollPane({ - showArrows: true, - autoReinitialise: true, - verticalArrowPositions: 'os', - horizontalArrowPositions: 'os' - }); - }; - function openEditFormGivenSegment(option) { var idsegment = option.attr("data-idsegment"); @@ -890,103 +534,6 @@ Segmentation = (function($) { } } - var doDragDropBindings = function(){ - $(self.form).find(".segment-nav div > ul > li > ul > li").sortable({ - cursor: 'move', - revert: 10, - revertDuration: 0, - snap: false, - helper: 'clone', - appendTo: 'body' - }); - - $(self.form).find(".metricListBlock").droppable({ - hoverClass: "hovered", - drop: function( event, ui ) { - $(this).find("select").val(ui.draggable.parent().attr("data-metric")).trigger("change"); - } - }); - - $(self.form).find(".segment-add-row > div").droppable({ - hoverClass: "hovered", - drop: function( event, ui ) { - $(this).find("a").trigger("click", [ui.draggable.parent().attr("data-metric")]); - if($(this).find("a > span").length == 0){ - revokeInitialStateRows(); - appendSpecifiedRowHtml([ui.draggable.parent().attr("data-metric")]); - } - } - }); - - $(self.form).find(".segment-add-or > div").droppable({ - hoverClass: "hovered", - drop: function( event, ui ) { - $(this).find("a").trigger("click", [ui.draggable.parent().attr("data-metric")]); - } - }); - }; - - var searchSegments = function(search){ - // pre-process search string to normalized form - search = normalizeSearchString(search); - - // --- - // clear all previous search highlights and hide all categories - // to allow further showing only matching ones, while others remain invisible - clearSearchMetricHighlight(); - $(self.form).find('.segment-nav div > ul > li').hide(); - var curStr = ""; - var curMetric = ""; - - // 1 - do most obvious selection -> mark whole categories matching search string - // also expand whole category - $(self.form).find('.segment-nav div > ul > li').each( function(){ - curStr = normalizeSearchString($(this).find("a.metric_category").text()); - if(curStr.indexOf(search) > -1) { - $(this).addClass("searchFound"); - $(this).find("ul").show(); - $(this).find("li").show(); - $(this).show(); - } - } - ); - - // 2 - among all unselected categories find metrics which match and mark parent as search result - $(self.form).find(".segment-nav div > ul > li:not(.searchFound)").each(function(){ - var parent = this; - $(this).find("li").each( function(){ - var curStr = normalizeSearchString($(this).text()); - var curMetric = normalizeSearchString($(this).attr("data-metric")); - $(this).hide(); - if(curStr.indexOf(search) > -1 || curMetric.indexOf(search) > -1){ - $(this).show(); - $(parent).find("ul").show(); - $(parent).addClass("searchFound").show(); - } - }); - }); - - if( $(self.form).find("li.searchFound").length == 0) - { - $(self.form).find("div > ul").prepend('<li class="no_results"><a>'+self.translations['General_SearchNoResults']+'</a></li>').show(); - } - // check if search allow flag was revoked - then clear all search results - if(self.searchAllowed == false) - { - clearSearchMetricHighlight(); - self.searchAllowed = true; - } - - }; - - var clearSearchMetricHighlight = function(){ - $(self.form).find('.no_results').remove(); - $(self.form).find('.segment-nav div > ul > li').removeClass("searchFound").show(); - $(self.form).find('.segment-nav div > ul > li').removeClass("others").show(); - $(self.form).find('.segment-nav div > ul > li > ul > li').show(); - $(self.form).find('.segment-nav div > ul > li > ul').hide(); - }; - var normalizeSearchString = function(search){ search = search.replace(/^\s+|\s+$/g, ''); // trim search = search.toLowerCase(); @@ -1012,6 +559,7 @@ Segmentation = (function($) { } // remove any remaining forms + self.form = getFormHtml(); self.target.prepend(self.form); @@ -1025,13 +573,8 @@ Segmentation = (function($) { self.form.addClass('anchorRight'); } - placeSegmentationFormControls(); - - // needs to be done before jQuery selects are built, as angular compiler screws up the selected values - piwikHelper.compileAngularComponents(self.target); - if(mode == "edit") { - $(self.form).find('.enable_all_users_select > option[value="' + segment.enable_all_users + '"]').prop("selected",true); + var userSelector = $(self.form).find('.enable_all_users_select > option[value="' + segment.enable_all_users + '"]').prop("selected",true); // Replace "Visible to me" by "Visible to $login" when user is super user if(hasSuperUserAccessAndSegmentCreatedByAnotherUser(segment)) { @@ -1040,6 +583,9 @@ Segmentation = (function($) { $(self.form).find('.visible_to_website_select > option[value="'+segment.enable_only_idsite+'"]').prop("selected",true); $(self.form).find('.auto_archive_select > option[value="'+segment.auto_archive+'"]').prop("selected",true); + if (segment.definition != ""){ + self.form.find('[piwik-segment-generator]').attr('segment-definition', segment.definition); + } } makeDropList(".enable_all_users" , ".enable_all_users_select"); @@ -1058,6 +604,8 @@ Segmentation = (function($) { $(".segmentListContainer", self.target).hide(); self.target.closest('.segmentEditorPanel').addClass('editing'); + + piwikHelper.compileAngularComponents(self.target); }; var closeForm = function () { @@ -1065,34 +613,14 @@ Segmentation = (function($) { self.target.closest('.segmentEditorPanel').removeClass('editing'); }; - var parseForm = function(){ - var segmentStr = ""; - $(self.form).find(".segment-rows").each( function(){ - var subSegmentStr = ""; - - $(this).find(".segment-row").each( function(){ - if(subSegmentStr != ""){ - subSegmentStr += ","; // OR operator - } - $(this).find(".segment-row-inputs").each( function(){ - var metric = $(this).find(".metricList option:selected").val(); - var match = $(this).find(".metricMatchBlock > select option:selected").val(); - var value = $(this).find(".segment-input input").val(); - subSegmentStr += metric + match + encodeURIComponent(value); - }); - }); - if(segmentStr != "") - { - segmentStr += ";"; // add AND operator between segment blocks - } - segmentStr += subSegmentStr; - }); - return segmentStr - }; + function getSegmentGeneratorController() + { + return angular.element(self.form.find('.segment-generator')).scope().segmentGenerator; + } var parseFormAndSave = function(){ var segmentName = $(self.form).find(".segment-content > h3 >span").text(); - var segmentStr = parseForm(); + var segmentStr = getSegmentGeneratorController().getSegmentString(); var segmentId = $(self.form).find('.available_segments_select > option:selected').attr("data-idsegment"); var user = $(self.form).find(".enable_all_users_select option:selected").val(); var autoArchive = $(self.form).find(".auto_archive_select option:selected").val() || 0; |