diff --git a/frontend/frontend/setup_tool.py b/frontend/frontend/setup_tool.py index 68cff31..4a39921 100644 --- a/frontend/frontend/setup_tool.py +++ b/frontend/frontend/setup_tool.py @@ -6,6 +6,15 @@ I_PARENT = 3 # not in use def build_xpathes(item_tag_ids, html_json): shared_tag_stack = []; +def _get_fork_stack(stacks): + first = stacks.itervalues().next() # just first stack + for i in range(0, len(first)): + tag = first[i] + for name in stacks: + if tag != stacks[name][i]: + return stacks[name][:i] + return first + def _build_parent_stack(html_json, tag_id): tag_stack = [] @@ -27,17 +36,14 @@ def _build_parent_stack(html_json, tag_id): def _find_tags_by_tag_names(html_json, parent_tag_names): tags = [] - tag_stack = [] def walk_by_tag(tag, depth): - tag_stack.append(tag) if tag[I_TAGNAME] == parent_tag_names[depth]: if depth == len(parent_tag_names)-1: # is a tie - tags.append((tag, list(tag_stack))) + tags.append(tag) elif depth < len(parent_tag_names)-1: for subtag in tag[I_CHILDREN]: walk_by_tag(subtag, depth+1) - tag_stack.pop() walk_by_tag(html_json, 0) return tags @@ -56,57 +62,33 @@ class PathItem: return '..' if self.go_parent else '%s[%s]' % (self.child_tag, self.child_index+1) -def _build_path(stack, target_stack): - fork = None - for fork_i in xrange(0, len(stack)): - if stack[fork_i] == target_stack[fork_i]: - fork = stack[fork_i] - else: - fork_i -= 1 - break - +def _build_path(stack): path = [] - # shifts to parent; like '..' in xpath - for i in xrange(fork_i, len(stack)): - path.append(PathItem(go_parent=True)) - - # address by children with indexes; like 'tag[n]' in xpath - for i in xrange(fork_i, len(target_stack)): - tag = target_stack[i] - tag_name = tag[I_TAGNAME] - parent = target_stack[i-1] - tags = parent[I_CHILDREN] + for i in range(0, len(stack)-1): idx = 0 - for tag_ in tags: - if tag_[I_TAGNAME] == tag_name: - if tag_ == tag: + tag = stack[i] + search = stack[i+1] + for tag_ in tag[I_CHILDREN]: + if tag_[I_TAGNAME] == search[I_TAGNAME]: + if tag_ == search: break idx += 1 - path.append(PathItem(child_tag=tag_name, child_index=idx)) - + path.append(PathItem(child_tag=search[I_TAGNAME], child_index=idx)) return path - -def _find_tag(html_json, source_tag_info, path): - tag = source_tag_info[0] - tag_stack = source_tag_info[1] - stack_i = len(tag_stack)-1 +def _find_tag(html_json, tag, path): for step in path: - if step.go_parent: - stack_i -= 1 - tag = tag_stack[stack_i] - else: - idx = step.child_index - next = None - for child in tag[I_CHILDREN]: - if child[I_TAGNAME] == step.child_tag: - if idx == 0: - next = child - break - idx -= 1 - if next is None: - return None - tag = next + idx = step.child_index + next = None + for child in tag[I_CHILDREN]: + if child[I_TAGNAME] == step.child_tag: + if idx == 0: + next = child + break + idx -= 1 + if next is None: + return None + tag = next return tag def get_selection_tag_ids(item_tag_ids, html_json): @@ -116,32 +98,32 @@ def get_selection_tag_ids(item_tag_ids, html_json): for name in item_tag_ids: tag_id = item_tag_ids[name] parent_stacks[name] = _build_parent_stack(html_json, tag_id) + #import pdb; pdb.set_trace() + # get fork + fork_stack = _get_fork_stack(parent_stacks) + + # get fork path + fork_path = [tag[I_TAGNAME] for tag in fork_stack] - # get first item and get his path - first_name, parent_stack = parent_stacks.popitem() - parent_tag_names = [tag[I_TAGNAME] for tag in parent_stack] + # get pathes for items + fork_len = len(fork_path) - 1 + selection_pathes = {name:_build_path(parent_stacks[name][fork_len:]) for name in parent_stacks} - # find tags for first item - tags = _find_tags_by_tag_names(html_json, parent_tag_names) - - # get pathes for another items - selection_pathes = {} - for name in parent_stacks: - selection_pathes[name] = _build_path(parent_stack, parent_stacks[name]) + # get fork tags + fork_tags = _find_tags_by_tag_names(html_json, fork_path) # get selection ids - selection_ids = {name:[] for name in item_tag_ids} - for tag_info in tags: + selection_ids = {name:[] for name in selection_pathes} + for fork_tag in fork_tags: ids = {} for name in selection_pathes: - tag = _find_tag(html_json, tag_info, selection_pathes[name]) + tag = _find_tag(html_json, fork_tag, selection_pathes[name]) if tag is not None: ids[name] = tag[I_ATTRS]['tag-id'] else: ids = None break if ids is not None: - selection_ids[first_name].append(tag_info[0][I_ATTRS]['tag-id']) for name in selection_pathes: selection_ids[name].append(ids[name]) diff --git a/frontend/frontend/static/frontend/assets/js/setup-tool.js b/frontend/frontend/static/frontend/assets/js/setup-tool.js index e6577c6..c8e8bb3 100644 --- a/frontend/frontend/static/frontend/assets/js/setup-tool.js +++ b/frontend/frontend/static/frontend/assets/js/setup-tool.js @@ -5,8 +5,8 @@ var MODE_INACTIVE = 1, MODE_PICKED = 3; var itemsData = { - title: { id: null, elementHoverBg: '#FFEB0D', elementSelectedBg: '#006dcc', mode: MODE_INACTIVE, name: 'title' }, - description: { id: null, elementHoverBg: '#FFEB0D', elementSelectedBg: '#2f96b4', mode: MODE_INACTIVE, name: 'description' } + title: { id: null, elementHoverBg: '#FFEB0D', elementSelectedBg: '#006dcc', elementCalcSelectedBg:"#0044CC", mode: MODE_INACTIVE, name: 'title' }, + description: { id: null, elementHoverBg: '#FFEB0D', elementSelectedBg: '#2f96b4', elementCalcSelectedBg:"#5bc0de", mode: MODE_INACTIVE, name: 'description' } }; var curItemData = null; @@ -15,6 +15,7 @@ var curItemData = null; // +++ calculation of all selections on server side //// +// used only for getting of csrftoken and putting it into request header; I'm not sure if it's required function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie != '') { @@ -61,6 +62,29 @@ function buildJsonFromHtml(doc) { return iframeHtmlJson; } +var calculatedSelection = { + _selected_elements: { + 'title': [], + 'description': [] + }, + + selectIds: function(data) { + // unselect old elements + alert('To be implemented'); + // select current elements + } +}; + +function updateCalculatedSelection(data) { + for (var name in data) { + var ids = data[name], + itemData_ = itemsData[name]; + ids.forEach(function(id){ + $('iframe').contents().find('*[tag-id='+ curItemData.id +']')[0]; + }); + } +} + function calcAllSelections() { var htmlJson = buildJsonFromHtml($('iframe').contents()); @@ -77,7 +101,9 @@ function calcAllSelections() { contentType: "application/json; charset=utf-8", dataType: "json", headers: {"X-CSRFToken": getCookie('csrftoken')}, - success: function(data){console.log(data);}, + success: function(data){ + console.log(data); + }, failure: function(errMsg) { console.log('Error:'+ errMsg); } @@ -113,54 +139,86 @@ function updateButtonAndData(itemData, new_mode, tag_id){ var BG_DATA_KEY = 'st-origin-background'; -var PICKED_NAMES_KEY = 'st-picked-item-names'; +var PICKED_NAMES_KEY = 'st-selected-item-names'; +var CALC_SELECTED_NAMES_KEY = 'st-calculated-selected-item-names'; -function setBg(element, bg, pick) { +var BG_TYPE_HOVER = 1 + BG_TYPE_SELECT = 2, + BG_TYPE_CALC_SELECT = 3; + +function setBg(element, bg, type) { // save origin background if it's not saved if (typeof($(element).data(BG_DATA_KEY)) == 'undefined') $(element).data(BG_DATA_KEY, $(element).css('background')); - // if it's picked element we push the item id into array - if (pick) { // redo for multiselect - if (typeof($(element).data(PICKED_NAMES_KEY)) == 'undefined') - $(element).data(PICKED_NAMES_KEY, []); - $(element).data(PICKED_NAMES_KEY).push(curItemData.name); + var key = null; + switch (type) { + BG_TYPE_HOVER: + break; + BG_TYPE_SELECT: + key = PICKED_NAMES_KEY; + break; + BG_TYPE_CALC_SELECT: + key = CALC_SELECTED_NAMES_KEY; + break; } + // if it's picked element we push the item id into array + if (key) { // redo for multiselect + if (typeof($(element).data(key)) == 'undefined') + $(element).data(key, []); + $(element).data(key).push(curItemData.name); + } + $(element).css({'background': bg}); } -function clearBg(element, unpick) { - if (unpick) { // redo for multiselect +function clearBg(element, type) { + if (type == BG_TYPE_SELECT) { // redo for multiselect var picked_names = $(element).data(PICKED_NAMES_KEY); // remove current item id from element if (picked_names.indexOf(curItemData.name) > -1) picked_names.splice(picked_names.indexOf(curItemData.name), 1); } + var pop = true; + // for first take selection color if element was selected - var picked_names = $(element).data(PICKED_NAMES_KEY); - if (typeof(picked_names) != 'undefined' && picked_names.length) { - var name = picked_names[picked_names.length-1]; - $(element).css({'background': itemsData[name].elementSelectedBg}); - } + [PICKED_NAMES_KEY, CALC_SELECTED_NAMES_KEY].forEach(function(key){ + if (pop) { + var picked_names = $(element).data(key); + if (typeof(picked_names) != 'undefined' && picked_names.length) { + var name = picked_names[picked_names.length-1]; + $(element).css({'background': itemsData[name].elementSelectedBg}); + } + pop = false; + } + }); // get original background if it saved - else if (typeof($(element).data(BG_DATA_KEY)) != 'undefined') + if (pop && typeof($(element).data(BG_DATA_KEY)) != 'undefined') $(element).css({'background': $(element).data(BG_DATA_KEY)}); } +function selectCalcElement(element, itemData) { + setBg(element, itemData.elementSelectedBg, BG_TYPE_CALC_SELECT); +} + +function UnselectCalcElement(element) { + clearBg(element, BG_TYPE_CALC_SELECT); +} + function selectElement(element, itemData) { - setBg(element, itemData.elementSelectedBg, true); + setBg(element, itemData.elementSelectedBg, BG_TYPE_SELECT); } function unselectElement(element) { - clearBg(element, true); + clearBg(element, BG_TYPE_SELECT); } function styleHoverElement(element) { - setBg(element, curItemData.elementHoverBg); + setBg(element, curItemData.elementHoverBg, BG_TYPE_HOVER); } function unstyleHoverElement(element) { - clearBg(element); + clearBg(element, BG_TYPE_HOVER); } function onIframeElementClick(event) {