<commit_before># Copyright (C) 2011 Orbeon, Inc.
#
# This program is free software; you can redistribute it and/or modify it under the terms of the
# GNU Lesser General Public License as published by the Free Software Foundation; either version
# 2.1 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# The full text of the license is available at http://www.gnu.org/copyleft/lesser.html

AjaxServer = ORBEON.xforms.server.AjaxServer
Builder = ORBEON.Builder
Controls = ORBEON.xforms.Controls
Event = YAHOO.util.Event
Events = ORBEON.xforms.Events
YD = YAHOO.util.Dom

# Rules defining when certain triggers are relevant
relevanceRules = do ->

    isNotEmpty = (gridTd) -> $(gridTd).find('.fr-grid-content').children().length > 0
    isUpload = (gridTd) -> isNotEmpty(gridTd) and $(gridTd).find('.fr-grid-content').hasClass('fb-upload')
    isEmptyUpload = (gridTd) ->
        # Check for presence of both spacer and photo placeholder, as both indicate an empty image and we are not sure which one will be shown
        # depending on whether the code replacing the spacer with the photo placeholder already ran or not
        spacer = '/ops/images/xforms/spacer.gif'
        photo = '/apps/fr/style/images/silk/photo.png'
        $(gridTd).find(".xforms-output-output[src $= '#{spacer}'], .xforms-output-output[src $= '#{photo}']").length > 0

    'fb-expand-trigger':            (gridTd) ->
                                        noDelimiter = ':not(.xforms-repeat-delimiter):not(.xforms-repeat-template):not(.xforms-repeat-begin-end):not(.xforms-group-begin-end)'
                                        grid = $(gridTd).closest('.fr-grid')
                                        if grid.hasClass('fr-norepeat')                                                                     # Regular table
                                            gridTd.rowSpan <= $(gridTd).parent().nextAll('tr' + noDelimiter).length                         #   Based on number of following non-internal rows
                                        else if grid.hasClass('fr-repeat-multiple-rows')                                                    # Repeat with multiple rows in each iteration
                                            gridTr =$(gridTd).parent()                                                                      #   Based on number of following row with the same parity
                                            oddEvenClass = if gridTr.hasClass('yui-dt-even') then 'yui-dt-even' else 'yui-dt-odd'           #   Rows with a different parity belong to a different iteration
                                            gridTd.rowSpan <= gridTr.next('.' + oddEvenClass).length
                                        else if grid.hasClass('fr-repeat-single-row') then false                                            # Repeat with single row: no expension possible
                                        else false                                                                                          # Catch all, which shouldn't happen
    'fb-shrink-trigger':            (gridTd) -> gridTd.rowSpan >= 2
    'fb-delete-trigger':            isNotEmpty
    'fb-edit-details-trigger':      isNotEmpty
    'fb-edit-validation-trigger':   isNotEmpty
    'fb-edit-items-trigger':        (gridTd) -> isNotEmpty(gridTd) and $(gridTd).find('.fr-grid-content').hasClass('fb-itemset')
    'fb-static-upload-empty':       (gridTd) -> isUpload(gridTd) and isEmptyUpload(gridTd)
    'fb-static-upload-non-empty':   (gridTd) -> isUpload(gridTd) and not isEmptyUpload(gridTd)

$ ->

    # Save reference to last operation that positioned the triggers
    lastPositionTriggers = null

    Builder.mouseEntersGridTdEvent.subscribe ({triggers, triggerGroups, gridTd}) ->
        gridTdId = gridTd.id
        lastPositionTriggers = ->
            # Move cell editor controls under this td
            gridTd = YD.get gridTdId
            if gridTd?
                if $(gridTd).children('.fb-hover').length == 0                          # Create a div.fb-hover inside the td, if there isn't one already
                    hoverDiv = $('<div>').addClass('fb-hover')
                    hoverDiv.append(triggerGroups)
                    hoverDiv.append($(gridTd).children())
                    $(gridTd).append(hoverDiv)
                $(triggerGroups).css('display', '')
                # Show/hide triggers depending on relevance rules
                for trigger in triggers
                    rule = relevanceRules[trigger.id]
                    triggerRelevant = if rule? then rule gridTd else true
                    trigger.style.display = if triggerRelevant then '' else 'none'
        lastPositionTriggers()

    Builder.mouseExitsGridTdEvent.subscribe ({triggerGroups, gridTd}) ->
        $(triggerGroups).hide()
        $('.fb-cell-editor').append(triggerGroups)
        fbHover = $(gridTd).children('.fb-hover')
        $(gridTd).append(fbHover.children())
        fbHover.remove()
        lastPositionTriggers = null

    # Change current cell on click on trigger
    Builder.triggerClickEvent.subscribe ({trigger}) ->
        # Send a DOMActivate to the closest xforms-activable ancestor
        activable = YD.getAncestorByClassName trigger, "xforms-activable"
        form = Controls.getForm activable
        event = new AjaxServer.Event form, activable.id, null, null, "DOMActivate"
        AjaxServer.fireEvents [event]

    # Reposition triggers after an Ajax request
    Events.ajaxResponseProcessedEvent.subscribe ->
        lastPositionTriggers() if lastPositionTriggers?<commit_msg>Don't remove div.fb-hover, not to cause blur event, fixes #44<commit_after># Copyright (C) 2011 Orbeon, Inc.
#
# This program is free software; you can redistribute it and/or modify it under the terms of the
# GNU Lesser General Public License as published by the Free Software Foundation; either version
# 2.1 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# The full text of the license is available at http://www.gnu.org/copyleft/lesser.html

AjaxServer = ORBEON.xforms.server.AjaxServer
Builder = ORBEON.Builder
Controls = ORBEON.xforms.Controls
Event = YAHOO.util.Event
Events = ORBEON.xforms.Events
YD = YAHOO.util.Dom

# Rules defining when certain triggers are relevant
relevanceRules = do ->

    isNotEmpty = (gridTd) -> $(gridTd).find('.fr-grid-content').children().length > 0
    isUpload = (gridTd) -> isNotEmpty(gridTd) and $(gridTd).find('.fr-grid-content').hasClass('fb-upload')
    isEmptyUpload = (gridTd) ->
        # Check for presence of both spacer and photo placeholder, as both indicate an empty image and we are not sure which one will be shown
        # depending on whether the code replacing the spacer with the photo placeholder already ran or not
        spacer = '/ops/images/xforms/spacer.gif'
        photo = '/apps/fr/style/images/silk/photo.png'
        $(gridTd).find(".xforms-output-output[src $= '#{spacer}'], .xforms-output-output[src $= '#{photo}']").length > 0

    'fb-expand-trigger':            (gridTd) ->
                                        noDelimiter = ':not(.xforms-repeat-delimiter):not(.xforms-repeat-template):not(.xforms-repeat-begin-end):not(.xforms-group-begin-end)'
                                        grid = $(gridTd).closest('.fr-grid')
                                        if grid.hasClass('fr-norepeat')                                                                     # Regular table
                                            gridTd.rowSpan <= $(gridTd).parent().nextAll('tr' + noDelimiter).length                         #   Based on number of following non-internal rows
                                        else if grid.hasClass('fr-repeat-multiple-rows')                                                    # Repeat with multiple rows in each iteration
                                            gridTr =$(gridTd).parent()                                                                      #   Based on number of following row with the same parity
                                            oddEvenClass = if gridTr.hasClass('yui-dt-even') then 'yui-dt-even' else 'yui-dt-odd'           #   Rows with a different parity belong to a different iteration
                                            gridTd.rowSpan <= gridTr.next('.' + oddEvenClass).length
                                        else if grid.hasClass('fr-repeat-single-row') then false                                            # Repeat with single row: no expension possible
                                        else false                                                                                          # Catch all, which shouldn't happen
    'fb-shrink-trigger':            (gridTd) -> gridTd.rowSpan >= 2
    'fb-delete-trigger':            isNotEmpty
    'fb-edit-details-trigger':      isNotEmpty
    'fb-edit-validation-trigger':   isNotEmpty
    'fb-edit-items-trigger':        (gridTd) -> isNotEmpty(gridTd) and $(gridTd).find('.fr-grid-content').hasClass('fb-itemset')
    'fb-static-upload-empty':       (gridTd) -> isUpload(gridTd) and isEmptyUpload(gridTd)
    'fb-static-upload-non-empty':   (gridTd) -> isUpload(gridTd) and not isEmptyUpload(gridTd)

$ ->

    # Save reference to last operation that positioned the triggers
    lastPositionTriggers = null

    Builder.mouseEntersGridTdEvent.subscribe ({triggers, triggerGroups, gridTd}) ->
        gridTdId = gridTd.id
        lastPositionTriggers = ->
            # Move cell editor controls under this td
            gridTd = YD.get gridTdId
            if gridTd?
                if $(gridTd).children('.fb-hover').length == 0                          # Create a div.fb-hover inside the td, if there isn't one already
                    hoverDiv = $('<div>').addClass('fb-hover')
                    hoverDiv.append(triggerGroups)
                    hoverDiv.append($(gridTd).children())
                    $(gridTd).append(hoverDiv)
                $(triggerGroups).css('display', '')
                # Show/hide triggers depending on relevance rules
                for trigger in triggers
                    rule = relevanceRules[trigger.id]
                    triggerRelevant = if rule? then rule gridTd else true
                    trigger.style.display = if triggerRelevant then '' else 'none'
        lastPositionTriggers()

    # We leave the div.fb-hover that was created on mouseEntersGridTdEvent, as removing it would dispatch a blur to the control
    # See: https://github.com/orbeon/orbeon-forms/issues/44
    Builder.mouseExitsGridTdEvent.subscribe ({triggerGroups, gridTd}) ->
        $(triggerGroups).hide()
        $('.fb-cell-editor').append(triggerGroups)
        lastPositionTriggers = null

    # Change current cell on click on trigger
    Builder.triggerClickEvent.subscribe ({trigger}) ->
        # Send a DOMActivate to the closest xforms-activable ancestor
        activable = YD.getAncestorByClassName trigger, "xforms-activable"
        form = Controls.getForm activable
        event = new AjaxServer.Event form, activable.id, null, null, "DOMActivate"
        AjaxServer.fireEvents [event]

    # Reposition triggers after an Ajax request
    Events.ajaxResponseProcessedEvent.subscribe ->
        lastPositionTriggers() if lastPositionTriggers?
{'fraction_non_alphanumeric': 0.09721048182586645, 'fraction_numerical': 0.0020287404902789518, 'mean_word_length': 1.8983341499265065, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 41, 'https://': 1, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 66, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6989244', 'n_tokens_mistral': 3053, 'n_tokens_neox': 2928, 'n_words': 861}