Mercurial Hosting > nabble
view src/nabble/modules/poll/poll.naml @ 19:18cf4872fd7f
remove anonymous posting
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 29 May 2020 22:58:25 -0600 |
parents | 7ecd1a4ef557 |
children |
line wrap: on
line source
=== Permission === <macro name="create_poll_permission"> Create_poll </macro> <macro name="can_create_poll_in" requires="user" dot_parameter="node_attr"> <n.set_local_user.this_user /> <n.set_local_node.node_attr/> <n.both> <condition1.local_user.is_registered/> <condition2.either> <condition1.local_user.is_site_admin/> <condition2.local_user.has_permission node="[n.local_node/]" permission_node="[n.local_node.app_or_root/]" permission="[n.create_poll_permission/]" /> </condition2.either> </n.both> </macro> <override_macro name="all_permissions_list"> <n.overridden /> <n.create_poll_permission/>, </override_macro> <override_macro name="permission_rows"> <n.overridden /> <n.permission_row permission = "[n.create_poll_permission/]" description="[t]Who can create polls.[/t]" administrators_cell = "true" /> </override_macro> === Node Message === <override_macro name="node_message_as_html" requires="node"> <n.overridden /> <n.comment.> If this is a topic page (which calls the "message_text" command), then show the poll. Otherwise (email messages), print a link to the poll. </n.comment.> <n.if.is_in_command name="email_message"> <then.poll_link/> <else.poll/> </n.if.is_in_command> </override_macro> <macro name="poll_link" requires="node"> <n.if.has_poll> <then> <div style="background-color:#FFFADB;border:#EDDD79 solid 1px;margin-top:1em;padding:.5em"> <b><t>This message has a poll</t></b> -- <t>Visit the link below if you want to participate:</t><br/> <a href="[n.url/]"><n.url/></a> </div> </then> </n.if.has_poll> </macro> <override_macro name="message_as_text" requires="message" unindent="true"> <n.overridden/> <n.if.is_in_command name="node_message_block"> <then.if.message_block_node.has_poll> <then> <n.crlf/>[<t>Poll</t>] <t>This message has a poll</t> / <t>Visit the link below if you want to participate:</t> <n.message_block_node.url/> </then> </then.if.message_block_node.has_poll> </n.if.is_in_command > </override_macro> === New post page === <override_macro name="new_post_extra_fields" requires="node_page"> <n.overridden/> <n.if.both condition1="[n.page_node.is_app/]" condition2="[n.visitor.can_create_poll_in.page_node/]"> <then> <div class="extra-fields"> <img src="/images/add.png" width="12" height="12" style="margin-top:.2em"/> <n.add_poll_form/> </div> </then> </n.if.both> </override_macro> <override_macro name="init_new_post_custom_fields"> <n.overridden/> <n.if.visitor.can_create_poll_in.page_node> <then> <n.poll_max_choices_field.set_value value="1" /> <n.poll_allow_vote_change_field.set_value value="true" /> <n.poll_show_results_before_vote_field.set_value value="true" /> <n.poll_show_results_before_end_field.set_value value="true" /> </then> </n.if.visitor.can_create_poll_in.page_node> </override_macro> <override_macro name="save_new_post_custom_fields"> <n.overridden/> <n.if.visitor.can_create_poll_in.page_node> <then.new_node.save_new_poll/> </n.if.visitor.can_create_poll_in.page_node> </override_macro> === Edit post page === <override_macro name="edit_post_extra_fields" requires="node_page"> <n.overridden/> <n.if.both condition1="[n.page_node.parent_node.is_app/]" condition2="[n.visitor.can_create_poll_in.page_node/]"> <then> <div class="extra-fields"> <img src="/images/add.png" width="12" height="12" style="margin-top:.2em"/> <n.if.page_node.has_poll> <then.edit_poll_form/> <else.add_poll_form/> </n.if.page_node.has_poll> </div> </then> </n.if.both> </override_macro> <override_macro name="init_edit_post_custom_fields" requires="node_page"> <n.overridden/> <n.if.both condition1="[n.page_node.has_poll/]" condition2="[n.visitor.can_create_poll_in.page_node/]"> <then> <n.poll_max_choices_field.set_value value="[n.page_node.poll_max_choices/]" /> <n.poll_days_left_field.set_value value="[n.page_node.poll_days_left/]" /> <n.poll_allow_vote_change_field.set_value value="[n.page_node.poll_allow_vote_change/]" /> <n.poll_show_results_before_vote_field.set_value value="[n.page_node.poll_show_results_before_vote/]" /> <n.poll_show_results_before_end_field.set_value value="[n.page_node.poll_show_results_before_end/]" /> </then> </n.if.both> </override_macro> <override_macro name="save_edit_post_custom_fields" requires="node_page"> <n.overridden/> <n.if.both condition1="[n.page_node.has_poll/]" condition2="[n.visitor.can_create_poll_in.page_node/]"> <then> <n.edit_poll> <poll_max_choices> <n.get_int. default="1" exception="max_choices_field_not_integer"><n.poll_max_choices_field.value/></n.get_int.> </poll_max_choices> <poll_days_left><n.to_null_if. equals=""><n.poll_days_left_field.value/></n.to_null_if.></poll_days_left> <poll_allow_vote_change><n.poll_allow_vote_change_field.value/></poll_allow_vote_change> <poll_show_results_before_vote><n.poll_show_results_before_vote_field.value/></poll_show_results_before_vote> <poll_show_results_before_end><n.poll_show_results_before_end_field.value/></poll_show_results_before_end> </n.edit_poll> </then> <else.page_node.save_new_poll/> </n.if.both> </override_macro> === Error Handling === <override_macro name="custom_new_node_errors"> <n.overridden/> <n.poll_errors/> </override_macro> <override_macro name="custom_edit_post_errors"> <n.overridden/> <n.poll_errors/> </override_macro> <macro name="poll_errors" requires="error"> <n.exception. name="invalid_poll_format"> <t>Invalid poll parameters.</t> </n.exception.> <n.exception. name="days_field_not_integer"> <t>Poll duration must be a non-negative integer or blank.</t> </n.exception.> <n.exception. name="max_choices_field_not_integer"> <t>Poll maximum allowed choices must be a non-negative integer or blank.</t> </n.exception.> </macro> === Javascript Handler === <override_macro name="extra_call_later_handlers"> <n.overridden/> <n.poll_js/> </override_macro> === Other macros === <macro name="add_poll_form" requires="node_page"> <script type="text/javascript"> function addPoll() { $('#poll').show(); if ( $('#poll-options div').size() == 0 ) { addOption(false); addOption(false); } else updateOptions(); Nabble.resizeFrames(); }; function removeOption(e) { $(e).parent().remove(); updateOptions(); Nabble.resizeFrames(); }; function addOption(focus) { $('#poll-options').append('<n.javascript_string_encode.poll_option_input_row/>'); updateOptions(); if (focus) $('#poll-options div input').last().focus(); Nabble.resizeFrames(); }; function updateOptions() { var c = 1; $('#poll-options div').each(function() { $('a,span', this).remove(); $(this).prepend('<span>'+c+'.</span>'); if (c++ > 2) { $(this).append('<a class="removeOption" href="javascript:void(0)" onclick="removeOption(this)"><t>remove</t></a>'); } }); }; function removePoll() { $('input[name=poll_question]').val(''); $('#poll').hide(); }; <n.if.not.is_empty.poll_question_field.value> <then> $(document).ready(function() { updateOptions(); }); </then> </n.if.not.is_empty.poll_question_field.value> </script> <a href="javascript: void(0)" onclick="addPoll()"><t>Add new poll</t></a> <div id="poll" class="extra-field-details medium-border-color" style="[n.if.is_empty.poll_question_field.value][then]display:none[/then][/n.if.is_empty.poll_question_field.value]"> <table> <tr valign="top"> <td style="text-align:right;padding-top:.4em"><t>Question:</t></td> <td style="padding-left:1.8em"><n.poll_question_field.input type="text" size="40"/></td> </tr> <tr valign="top"> <td style="text-align:right;padding-top:.4em"><t>Answers:</t></td> <td style="padding-left:.7em"> <div id="poll-options" style="padding-bottom:.3em"> <n.get_parameter_values. name="poll_option"> <n.loop.poll_option_input_row.current_parameter_value/> </n.get_parameter_values.> </div> <a href="javascript: void addOption(true)"><t>Add new answer</t></a> </td> </tr> </table> <n.poll_settings/> <a href="javascript: void(0)" onclick="removePoll()"><t>Remove Poll</t></a> </div> </macro> <macro name="edit_poll_form" requires="node_page"> <script type="text/javascript"> Nabble.deletePoll = function(nodeId) { var call = '/template/NamlServlet.jtp?macro=delete_poll_js&node='+nodeId; if (confirm("<t>Delete this poll, including all votes?</t>")) { $.getScript(call, function() { notice('<t>Poll has been deleted.</t>', 2000, 2000); $('#poll').remove(); }); } return false; }; </script> <n.page_node.> <t>Poll</t> <div id="poll" class="extra-field-details medium-border-color"> <div class="weak-color" style="padding:.3em"> <div class="bold"><n.encode.poll_question/></div> <ul style="margin:.3em 0"> <n.poll_option_list.loop.> <li><n.current_string/></li> </n.poll_option_list.loop.> </ul> <n.poll_settings /> <a href="javascript: void(0)" onclick="Nabble.deletePoll([n.id/])"><t>Remove Poll</t></a> </div> </div> </n.page_node.> </macro> <macro name="poll_settings"> <div style="margin: .5em 0 .5em 1em"> <t>Multiple selections allowed:</t> <n.poll_max_choices_field.input type="text" size="2" maxlength="2"/><br /> <t>Poll ends after <t.number.poll_days_left_field.input type="text" size="2" maxlength="3"/> days (leave blank for unlimited).</t><br /> <n.poll_allow_vote_change_field.checkbox/> <label for="poll_allow_vote_change"><t>Allow vote changes</t></label><br /> <n.poll_show_results_before_vote_field.checkbox/> <label for="poll_show_results_before_vote"><t>Allow viewing results before vote</t></label><br /> <n.poll_show_results_before_end_field.checkbox/> <label for="poll_show_results_before_end"><t>Allow viewing results before end date (poll creators can always view the results)</t></label> </div> </macro> <macro name="save_new_poll" requires="node"> <n.if.not.is_empty.poll_question_field.value> <then> <n.set_poll> <poll_question><n.poll_question_field.value/></poll_question> <poll_options><n.get_parameter_values name="poll_option"/></poll_options> <poll_max_choices> <n.get_int. default="1" exception="max_choices_field_not_integer"><n.poll_max_choices_field.value/></n.get_int.> </poll_max_choices> <poll_days_left> <n.get_int. default="0" exception="days_field_not_integer"><n.poll_days_left_field.value/></n.get_int.> </poll_days_left> <poll_allow_vote_change><n.poll_allow_vote_change_field.value/></poll_allow_vote_change> <poll_show_results_before_vote><n.poll_show_results_before_vote_field.value/></poll_show_results_before_vote> <poll_show_results_before_end><n.poll_show_results_before_end_field.value/></poll_show_results_before_end> </n.set_poll> </then> </n.if.not.is_empty.poll_question_field.value> </macro> <macro name="poll_question_field" dot_parameter="do"> <n.field. name="poll_question"><n.do/></n.field.> </macro> <macro name="poll_max_choices_field" dot_parameter="do"> <n.field. name="poll_max_choices"><n.do/></n.field.> </macro> <macro name="poll_days_left_field" dot_parameter="do"> <n.field. name="poll_days_left"><n.do/></n.field.> </macro> <macro name="poll_allow_vote_change_field" dot_parameter="do"> <n.field. name="poll_allow_vote_change"><n.do/></n.field.> </macro> <macro name="poll_show_results_before_vote_field" dot_parameter="do"> <n.field. name="poll_show_results_before_vote"><n.do/></n.field.> </macro> <macro name="poll_show_results_before_end_field" dot_parameter="do"> <n.field. name="poll_show_results_before_end"><n.do/></n.field.> </macro> <macro name="poll_option_input_row" dot_parameter="poll_option"> <div class="nowrap"> <input type="text" class="poll_option" name="poll_option" size="30" value="[n.hide_null.poll_option/]" /> </div> </macro> <macro name="delete_poll_js"> <n.get_node_from_id. node_id="[n.get_parameter name='node'/]"> <n.delete_poll /> </n.get_node_from_id.> </macro> <macro name="poll" requires="node"> <n.comment.> Builds the poll interface. Since some options depend on the current visitor, we use javascript to set up some fields. Please look at the "poll_js" macro in order to understand how this poll UI is updated. </n.comment.> <n.if.has_poll> <then> <form method="POST" id="poll_form[n.id/]" onsubmit="return Nabble.vote([n.id/],[n.poll_max_choices/]);" accept-charset="UTF-8" > <input type="hidden" name="node" value="[n.id/]" /> <div class="medium-border-color border2 rounded" style="margin-top:1em;padding:1em"> <div class="big-title second-font"> <n.encode.poll_question/> </div> <n.explain_poll_max_choices/> <n.poll_option_list.loop.> <div style="margin:.4em 0 0 1em"> <span id="poll-option-input[n.option_id/]"></span> <label for="option[n.option_id/]"><n.encode.current_string/></label> <span id="poll-vote-count[n.option_id/]" class="weak-color" style="font-size:80%"></span> </div> </n.poll_option_list.loop.> <div style="margin-top:.7em"> <n.poll_submit_button/> <n.poll_total_votes/> </div> <n.poll_description_lines/> </div> </form> <n.call_later value="[n.id/]" param="poll_node_id"/> </then> </n.if.has_poll> </macro> <macro name="poll_js" requires="servlet"> <n.comment.> This is the javascript code that will update the poll controls and make them available to the users. </n.comment.> <n.param_loop. param="poll_node_id"> <n.get_node_from_id. node_id="[n.current_parameter_value/]"> <n.set_local_node.this_node /> <n.if.visitor.is_registered> <then> <n.poll_option_list.loop.> var input = '<n.local_node.poll_vote_input_field field_id="option[n.option_id/]" index="[n.current_index/]"/>'; $('#poll-option-input<n.option_id/>').html(input); </n.poll_option_list.loop.> <n.if.poll_has_ended> <then> var input = '<t>This poll is closed.</t>'; </then> <else> var txt_vote = "<t>Vote</t>"; var input = '<input type="submit" value="' + txt_vote + '"/>'; if (!<n.poll_visitor_can_vote/>) input = '<input type="submit" value="' + txt_vote + '" disabled="true"/>'; </else> </n.if.poll_has_ended> $('#poll-submit-button<n.id/>').html(input); </then> </n.if.visitor.is_registered> <n.if.poll_visitor_can_see_votes> <then> var total_votes = 0; <n.poll_vote_counts.loop.> var text = <n.current_string/> == 1? '(<t>1 vote</t>)' : '(<t><t.number.current_string/> votes</t>)'; $('#poll-vote-count<n.option_id/>').html(text); total_votes += <n.current_string/>; </n.poll_vote_counts.loop.> var text = '<t>Total votes:</t> ' + total_votes; $('#poll-total-votes<n.local_node.id/>').html(text).show(); </then> </n.if.poll_visitor_can_see_votes> </n.get_node_from_id.> </n.param_loop.> </macro> <macro name="poll_submit_button" requires="node"> <n.comment.> Creates the submit button. Initially, it is just a span with some default text. The content of the span is updated by javascript code (see "poll_js" macro for more info) </n.comment.> <span id="poll-submit-button[n.id/]" class="bold"> <n.if.poll_has_ended> <then><t>This poll is closed.</t></then> <else> <n.login_link.><t>Login to vote</t></n.login_link.> </else> </n.if.poll_has_ended> </span> </macro> <macro name="poll_total_votes" requires="node"> <n.comment.> The span below shows the total number of votes. This element is updated by javascript code (see "poll_js" macro for more info) </n.comment.> <span id="poll-total-votes[n.id/]" class="shaded-bg-color rounded" style="padding:.2em .4em;display:none"></span> </macro> <macro name="poll_description_lines"> <div class="weak-color" style="font-size:80%;margin-top:.6em"> <n.if.not.poll_allow_vote_change> <then> <t>You cannot change your vote after voting.</t><br/> </then> </n.if.not.poll_allow_vote_change> <n.if.poll_has_end_date> <then> <n.if.poll_has_ended> <then> <t>This poll ended on <t.date.poll_end_date.long_format/>.</t><br/> </then> <else> <t>This poll ends on <t.date.poll_end_date.long_format/>.</t><br/> <n.if.not.poll_show_results_before_end> <then> <t>Results will be shown only after poll has ended.</t><br/> </then> </n.if.not.poll_show_results_before_end> </else> </n.if.poll_has_ended> </then> </n.if.poll_has_end_date> <n.if.not.poll_show_results_before_vote> <then> <t>You have to vote before you can see the results.</t><br/> </then> </n.if.not.poll_show_results_before_vote> </div> </macro> <macro name="explain_poll_max_choices"> <n.if.not.equal value1="[n.poll_max_choices/]" value2="1"> <then> <div class="weak-color" style="font-size:80%"> <t>You can select up to <t.number.poll_max_choices/> options.</t> </div> </then> </n.if.not.equal> </macro> <macro name="vote_input_type" requires="node"> <n.if.equal value1="[n.poll_max_choices/]" value2="1"> <then>radio</then> <else>checkbox</else> </n.if.equal> </macro> <macro name="poll_vote_input_field" parameters="field_id, index" requires="node"> <n.comment.> Creates an input field for a poll option. There are some possibilities depending on the poll configuration and who is the visitor. </n.comment.> <n.if.poll_visitor_has_voted.index> <then> <n.if.poll_visitor_can_vote> <then> <input id="[n.field_id/]" type="[n.vote_input_type/]" name="vote" value="[n.index/]" checked="true" /> </then> <else> <input id="[n.field_id/]" type="[n.vote_input_type/]" name="vote" value="[n.index/]" checked="true" disabled="true" /> </else> </n.if.poll_visitor_can_vote> </then> <else> <n.if.poll_visitor_can_vote> <then> <input id="[n.field_id/]" type="[n.vote_input_type/]" name="vote" value="[n.index/]"/> </then> <else> <input id="[n.field_id/]" type="[n.vote_input_type/]" name="vote" value="[n.index/]" disabled="true" /> </else> </n.if.poll_visitor_can_vote> </else> </n.if.poll_visitor_has_voted.index> </macro> <override_macro name="javascript_library" requires="servlet"> <n.overridden/> <n.comment.> Javascript to validate and submit a poll vote. </n.comment.> <n.compress.> Nabble.vote = function(nodeId,maxChoices) { var vote_count = $('#poll_form'+nodeId+' input:checked').length; <![CDATA[ if (vote_count > maxChoices) { ]]> alert('<t>Please select no more than <t.number>'+maxChoices+'</t.number> options.</t>'); return false; } else if (vote_count == 0) { alert('<t>Please select at least one option.</t>'); return false; } var params = $('#poll_form'+nodeId).serialize(); var call = '/template/NamlServlet.jtp?macro=vote&'+params; var call2 = '/template/NamlServlet.jtp?macro=poll_js&poll_node_id='+nodeId; $.getScript(call, function() { notice('<t>Your vote has been submitted.</t>', 5000, 2000); $.getScript(call2); }); return false; }; </n.compress.> </override_macro> <macro name="vote"> <n.get_node_from_id. node_id="[n.get_parameter name='node'/]"> <n.poll_vote votes="[n.get_parameter_values name='vote'/]" /> </n.get_node_from_id.> </macro>