From 7e169e150f7a7b6f38e01c0079a3205b36a4f06f Mon Sep 17 00:00:00 2001 From: Andreas Schenkel Date: Mon, 11 Dec 2023 08:25:52 +0100 Subject: [PATCH 1/6] show author of note --- amd/build/board.min.js | 2 +- amd/build/board.min.js.map | 2 +- amd/src/board.js | 33 ++++++++++++++++- backup/moodle2/backup_board_stepslib.php | 7 ++-- classes/board.php | 46 ++++++++++++++++++++++++ db/install.xml | 1 + db/upgrade.php | 15 ++++++++ external.php | 2 ++ lang/en/board.php | 9 +++++ mod_form.php | 5 +++ scss/styles.scss | 11 ++++++ settings.php | 7 ++++ styles.css | 9 +++++ tests/board_test.php | 1 + version.php | 7 ++-- view.php | 10 ++++-- 16 files changed, 155 insertions(+), 12 deletions(-) diff --git a/amd/build/board.min.js b/amd/build/board.min.js index 1224f24..cab5332 100755 --- a/amd/build/board.min.js +++ b/amd/build/board.min.js @@ -5,6 +5,6 @@ define("mod_board/board",["exports","jquery","core/str","core/ajax","core/modal_ * @author Karen Holland * @copyrigt 2021 Brickfield Education Labs * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=function(settings){var strings={default_column_heading:"",post_button_text:"",cancel_button_text:"",remove_note_title:"",remove_note_text:"",remove_column_title:"",note_changed_title:"",note_changed_text:"",note_deleted_text:"",rate_note_title:"",rate_note_text:"",rate_remove_note_text:"",Ok:"",delete:"",Cancel:"",warning:"",modal_title_new:"",modal_title_edit:"",option_youtube:"",option_image:"",option_link:"",aria_newcolumn:"",aria_newpost:"",aria_deletecolumn:"",aria_movecolumn:"",aria_deletepost:"",aria_movepost:"",aria_editpost:"",aria_addmedia:"",aria_addmedianew:"",aria_deleteattachment:"",aria_postedit:"",aria_canceledit:"",aria_postnew:"",aria_cancelnew:"",aria_ratepost:"",invalid_file_extension:"",invalid_file_size_min:"",invalid_file_size_max:"",invalid_youtube_url:""},options=JSON.parse(settings.settings)||{},board=options.board||{},contextid=options.contextid;var reloadTimer=null,lastHistoryId=null,isEditor=options.isEditor||!1,usersCanEdit=options.usersCanEdit,userId=parseInt(options.userId)||-1,ownerId=parseInt(options.ownerId),mediaSelection=options.mediaselection||1,editingNote=0,isReadOnlyBoard=options.readonly||!1,ratingenabled=options.ratingenabled,sortby=options.sortby||1,editModal=null,enableblanktarget=1===parseInt(options.enableblanktarget),serviceCall=function(method,args,callback,failcallback){"board_history"!==method&&stopUpdating(),function(method,args,callback,failcallback){_ajax.default.call([{methodname:"mod_board_"+method,args:args,done:function(data){callback(data)},fail:function(error){_notification.default.exception(error),failcallback&&failcallback(error)}}])}(method,args,(function(){callback&&callback.apply(null,arguments),"board_history"!==method&&"get_board"!=method&&updateBoard(!0)}),failcallback)},getNote=function(ident){return(0,_jquery.default)(".board_note[data-ident='"+ident+"']")},getNoteTextForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_text")},getNoteHeadingForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_heading")},getNoteBorderForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_border")},getNoteAttachmentsForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_attachment")},textIdentifierForNote=function(note){var noteText=getNoteTextForNote(note).html(),noteHeading=getNoteHeadingForNote(note).html(),noteAttachment=attachmentDataForNote(note);return noteHeading.length>0?noteHeading:noteText.length>0?noteText.replace(//gi," ").replace(/\n/g," ").split(/\s+/).slice(0,5).join(" "):noteAttachment.info&¬eAttachment.info.length>0?noteAttachment.info:null},updateNoteAria=function(noteId){var note=getNote(noteId),columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text();if(noteId){var noteIdentifier=textIdentifierForNote(note),deleteNoteString=strings.aria_deletepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier);note.find(".delete_note").attr("aria-label",deleteNoteString).attr("title",deleteNoteString);var moveNoteString=strings.aria_movepost.replace("{post}",noteIdentifier);note.find(".move_note").attr("aria-label",moveNoteString).attr("title",moveNoteString);var editNoteString=strings.aria_editpost.replace("{post}",noteIdentifier);note.find(".edit_note").attr("aria-label",editNoteString).attr("title",editNoteString),note.find(".mod_board_rating").attr("aria-label",strings.aria_ratepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)),note.find(".note_ariatext").html(noteIdentifier)}},updateColumnAria=function(columnId){var column=(0,_jquery.default)(".board_column[data-ident="+columnId+"]"),columnIdentifier=column.find(".mod_board_column_name").text(),newNoteString=strings.aria_newpost.replace("{column}",columnIdentifier),moveColumnString=strings.aria_movecolumn.replace("{column}",columnIdentifier),deleteColumnString=strings.aria_deletecolumn.replace("{column}",columnIdentifier);column.find(".newnote").attr("aria-label",newNoteString).attr("title",newNoteString),column.find(".mod_column_move").attr("aria-label",moveColumnString).attr("title",moveColumnString),column.find(".delete_column").attr("aria-label",deleteColumnString).attr("title",deleteColumnString),column.find(".board_note").each((function(index,note){updateNoteAria((0,_jquery.default)(note).data("ident"))}))},stopNoteEdit=function(){if(editingNote){var note=getNote(editingNote);if(note){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())}editingNote=0}else getNote(0).remove()};const sortAfterDelete=(columnID,sortorder)=>{let column=(columnID=>(0,_jquery.default)(".board_column[data-ident='".concat(columnID,"'] .board_column_content")))(columnID);column.children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so-1)}))};var setAttachment=function(note,attachment){var noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment){attachment?attachment.type+="":attachment={type:"0"};var attType=noteAttachment.find(".mod_board_type");attType.val(attachment.type?attachment.type:"0"),attType.val()>"0"&&(noteAttachment.find(".info").val(decodeText(attachment.info)),noteAttachment.find(".url").val(decodeText(attachment.url))),function(note){var noteAttachment=getNoteAttachmentsForNote(note),type=noteAttachment.find(".mod_board_type").val(),attachmentInfo=noteAttachment.find(".info"),attachmentUrl=noteAttachment.find(".url"),attachmentFile=noteAttachment.find(".mod_board_file");type>"0"?(attachmentInfo.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_info"]),attachmentUrl.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_url"]),attachmentInfo.show(),2==type&&FileReader?(attachmentFile.show(),attachmentUrl.hide()):(attachmentFile.hide(),attachmentUrl.show())):(attachmentInfo.hide(),attachmentUrl.hide(),attachmentFile.hide(),attachmentInfo.val(""),attachmentUrl.val(""))}(note)}previewAttachment(note,attachment)},attachmentDataForNote=function(note){var attachment={type:0,info:null,url:null,filename:null,filecontents:null},noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment.length){attachment.type=noteAttachment.find(".mod_board_type").val(),attachment.info=encodeText(noteAttachment.find(".info").val()),attachment.url=encodeText(noteAttachment.find(".url").val());var fileElem=noteAttachment.find(".mod_board_file>input");fileElem.data("filename")&&(attachment.filename=fileElem.data("filename"),attachment.filecontents=fileElem.data("filecontents"))}return attachment.info&&attachment.info.length||attachment.url&&attachment.url.length||attachment.filename||(attachment.type=0),attachment},attachmentTypeToString=function(type){switch(type){case"1":return"youtube";case"2":return"image";case"3":return"link";default:return null}};var previewAttachment=function(note,attachment){var elem=note.find(".mod_board_preview");if(attachment||(attachment=attachmentDataForNote(note)),getNoteTextForNote(note).html().length?elem.removeClass("mod_board_notext"):elem.addClass("mod_board_notext"),elem.removeClass("wrapper_youtube"),elem.removeClass("wrapper_image"),elem.removeClass("wrapper_url"),attachment.filename&&2==parseInt(attachment.type))elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();else if(attachment.url){const blanktarget=enableblanktarget?' target="_blank"':"";switch(parseInt(attachment.type)){case 1:{let url=(url=>{let videoID=url.match(/(\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/);return videoID&&void 0!==videoID[2]&&11===videoID[2].length?"https://www.youtube-nocookie.com/embed/".concat(videoID[2]):null})(attachment.url);null===url?elem.html(strings.invalid_youtube_url):(elem.html(''),elem.addClass("wrapper_youtube").addClass("position-relative")),elem.show()}break;case 2:elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();break;case 3:elem.html('"+(attachment.info||attachment.url)+""),elem.addClass("wrapper_url"),elem.show();break;default:elem.html(""),elem.hide()}}else elem.html(""),elem.hide()},addNote=function(columnid,ident,heading,content,attachment,owner,sortorder,rating){var ismynote=owner.id==userId||!ident,iseditable=isEditor||ismynote&&!isReadOnlyBoard;if(!ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}if(3==sortby){(0,_jquery.default)(".board_column[data-ident='".concat(columnid,"'] .board_column_content")).children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>=parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so+1)}))}var note=(0,_jquery.default)('
');ismynote&¬e.addClass("mod_board_mynote"),iseditable&¬e.addClass("mod_board_editablenote"),ismynote||iseditable||note.addClass("mod_board_nosort");var notecontent=(0,_jquery.default)('
'),notecontrols=(0,_jquery.default)('
'),noteHeading=(0,_jquery.default)('
'+(heading||"")+"
"),noteBorder=(0,_jquery.default)('
'),noteText=(0,_jquery.default)('
'+(content||"")+"
"),noteAriaText=(0,_jquery.default)(''),attachmentPreview=(0,_jquery.default)('
');notecontent.append(noteHeading),notecontent.append(noteBorder),notecontent.append(noteText),notecontent.append(noteAriaText),notecontent.append(attachmentPreview),note.append(notecontent);var columnContent=(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_content"),beginEdit=()=>{!function(ident){if(editingNote){if(editingNote==ident)return;stopNoteEdit()}if(ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}var note=getNote(ident);note&&(showModalForm(note),ident&&(editingNote=ident))}(ident)};if(ident){if(ratingenabled){note.addClass("mod_board_rateablenote");var rateElement=(0,_jquery.default)('
'.concat(rating,"
"));handleAction(rateElement,(()=>{!function(ident){if(ratingenabled&&!isReadOnlyBoard){var note=getNote(ident),rating=note.find(".mod_board_rating");rating.data("disabled")||(rating.data("disabled",!0),serviceCall("can_rate_note",{id:ident},(function(result){if(result.canrate){const rateRemoveText=result.hasrated?strings.rate_remove_note_text:strings.rate_note_text;_notification.default.confirm(strings.rate_note_title,rateRemoveText,strings.Ok,strings.Cancel,(function(){serviceCall("rate_note",{id:ident},(function(result){result.status&&(lastHistoryId=result.historyid,rating.html(" ".concat(result.rating," ")),2==sortby&&sortNotes(note.closest(".board_column_content"))),rating.data("disabled",!1)}))})).then((function(rateModal){rateModal.getRoot().on(_modal_events.default.hidden,(function(){rating.data("disabled",!1)}))}))}})))}}(ident)})),notecontrols.append(rateElement)}if(iseditable){var removeElement=(0,_jquery.default)('
');if(handleAction(removeElement,(()=>{!function(ident){_notification.default.confirm(strings.remove_note_title,strings.remove_note_text,strings.delete,strings.Cancel,(function(){serviceCall("delete_note",{id:ident},(function(result){if(result.status){lastHistoryId=result.historyid;let note=getNote(ident);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}}))}))}(ident)})),notecontrols.append(removeElement),1==usersCanEdit||isEditor){var moveElement=(0,_jquery.default)('
');notecontrols.append(moveElement),_movenotesdialog.default.init(ownerId,moveNote)}var editElement=(0,_jquery.default)('
');notecontrols.append(editElement),handleAction(editElement,(()=>{beginEdit()})),updateSortable(),setAttachment(note,attachment)}else previewAttachment(note,attachment);note.append(notecontrols),handleAction(notecontent,(()=>fullScreenNote(ident,notecontent))),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide());var lastOne=columnContent.find(".board_note").last();lastOne.length?note.insertAfter(lastOne):columnContent.prepend(note)}else(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_newcontent").append(note),note.hide(),beginEdit()},addColumn=function(ident,name,locked,notes,colour){let headerStyle='style="border-top: 10px solid #'.concat(colour,'"');var iseditable=isEditor,nameCache=null,column=(0,_jquery.default)('
')),columnHeader=(0,_jquery.default)('
'),columnSort=(0,_jquery.default)('
'),columnName=(0,_jquery.default)('
'+name+"
"),columnContent=(0,_jquery.default)('
'),columnNewContent=(0,_jquery.default)('
');if(3!=sortby&&columnHeader.append(columnSort),columnHeader.append(columnName),options.hideheaders&&columnName.addClass("d-none"),columnSort.on("click",(function(){sortNotes(columnContent,!0)})),iseditable){column.addClass("mod_board_editablecolumn");const lockIcon=locked?"fa-lock":"fa-unlock",lockElement=(0,_jquery.default)('
')),lockstring=locked?"aria_column_locked":"aria_column_unlocked";(0,_str.get_string)(lockstring,"mod_board",name).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)})),handleAction(lockElement,(()=>{const lockColumn="true"!==column.attr("data-locked");serviceCall("lock_column",{id:ident,status:lockColumn},(function(result){const columnName=column.find(".mod_board_column_name").text();result.status&&(lockColumn?(lockElement.removeClass("fa-unlock").addClass("fa-lock"),column.attr("data-locked","true"),column.find(".board_button.newnote").addClass("d-none"),(0,_str.get_string)("aria_column_locked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))):(lockElement.removeClass("fa-lock").addClass("fa-unlock"),column.attr("data-locked","false"),column.find(".board_button.newnote").removeClass("d-none"),(0,_str.get_string)("aria_column_unlocked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))),lastHistoryId=result.historyid,updateSortable())}))})),columnHeader.append(lockElement),columnHeader.addClass("icon-size-3");const moveElement=(0,_jquery.default)('
');columnHeader.append(moveElement),_movecolumnsdialog.default.init(moveColumn);var removeElement=(0,_jquery.default)('
');handleAction(removeElement,(()=>{_notification.default.confirm(strings.remove_column_title,(0,_str.get_string)("remove_column_text","mod_board",getColumnName(ident)),strings.delete,strings.Cancel,(function(){serviceCall("delete_column",{id:ident},(function(result){result.status&&(column.remove(),lastHistoryId=result.historyid)}))}))})),columnHeader.append(removeElement)}if(column.append(columnHeader),column.append(columnContent),column.append(columnNewContent),iseditable&&(!function(elem,callback,callBeforeOnKeyEditing){if(elem.is(":editable"))throw new Error("handleEditableAction - must be called before setting the element as editable");elem.on("dblclick keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode)||elem.is(":editing"))return;if(e.preventDefault(),callBeforeOnKeyEditing&&callback(),elem.editable("open"),callBeforeOnKeyEditing)return}callback()}))}(columnName,(function(){nameCache=columnName.html()}),!0),columnName.editable({toggleFontSize:!1,closeOnEnter:!0,callback:function(data){data.content?serviceCall("update_column",{id:ident,name:columnName.html()},(function(result){result.status?(lastHistoryId=result.historyid,updateColumnAria(ident)):(columnName.html(nameCache),nameCache=null)}),(function(){columnName.html(nameCache),nameCache=null})):(columnName.html(nameCache),nameCache=null)}})),!isReadOnlyBoard){const newNoteButton=(0,_jquery.default)('
');columnNewContent.append(newNoteButton),"true"===column.attr("data-locked")&&newNoteButton.addClass("d-none"),handleAction(columnNewContent.find(".newnote"),(function(){addNote(ident,0,null,null,null,{id:userId},0,0)}))}var lastOne=(0,_jquery.default)(".mod_board .board_column_hasdata").last();if(lastOne.length?column.insertAfter(lastOne):(0,_jquery.default)(".mod_board").append(column),notes)for(var index in notes){let sortorder=3==sortby?notes[index].sortorder:notes[index].timecreated;addNote(ident,notes[index].id,notes[index].heading,notes[index].content,{type:notes[index].type,info:notes[index].info,url:notes[index].url},{id:notes[index].userid},sortorder,notes[index].rating)}sortNotes(columnContent),updateColumnAria(ident),(isEditor||1==usersCanEdit)&&updateSortable(),isEditor&&columnSorting()};const getColumnName=id=>(0,_jquery.default)(".board_column[data-ident='".concat(id,"']")).find(".mod_board_column_name").html();const selectHeadingColour=()=>{let colCount=(0,_jquery.default)(".board_column").length-1,colourCount=options.colours.length;return options.colours[colCount%colourCount]};var updateNote=function(note,heading,data){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteText.html(data.content),noteHeading.html(data.heading),setAttachment(note,data.attachment),updateNoteAria(data.id),noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())},processBoardHistory=function(){serviceCall("board_history",{id:board.id,ownerid:ownerId,since:lastHistoryId},(function(boardhistory){for(var index in boardhistory){var item=boardhistory[index];if(item.boardid==board.id){var data=JSON.parse(item.content);if("add_note"==item.action){let sortorder=3==sortby?data.sortorder:data.timecreated;addNote(data.columnid,data.id,data.heading,data.content,data.attachment,{id:item.userid},sortorder,data.rating),updateNoteAria(data.id),sortNotes((0,_jquery.default)(".board_column[data-ident="+data.columnid+"] .board_column_content"))}else if("update_note"==item.action){let note=getNote(data.id),formModal=editModal,historyData=data;if(note){getNoteHeadingForNote(note);editingNote==data.id?_notification.default.confirm(strings.note_changed_title,strings.note_changed_text,strings.Ok,strings.Cancel,(function(){formModal.hide(),updateNote(note,0,historyData),stopNoteEdit()})):updateNote(note,0,data)}}else if("delete_note"==item.action){editingNote==data.id&&(_notification.default.alert(strings.warning,strings.note_deleted_text),stopNoteEdit());let note=getNote(data.id);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}else if("add_column"==item.action)addColumn(data.id,data.name,!1,{},selectHeadingColour());else if("move_column"==item.action){const board=(0,_jquery.default)(".mod_board");data.sortorder.forEach((column=>{board.find(".board_column[data-ident='".concat(column,"']")).detach().appendTo(board)}))}else if("update_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"'] .mod_board_column_name").html(data.name),updateColumnAria(data.id);else if("lock_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").attr("data-locked",data.locked),data.locked?(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").addClass("d-none"):(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").removeClass("d-none"),updateSortable();else if("delete_column"==item.action){var column=(0,_jquery.default)(".board_column[data-ident='"+data.id+"']");editingNote&&column.find('.board_note[data-ident="'+editingNote+'"]').length&&stopNoteEdit(),column.remove()}else if("rate_note"==item.action){var note=getNote(data.id);note.find(".mod_board_rating").html(data.rating),2==sortby&&sortNotes(note.closest(".board_column_content"))}lastHistoryId=item.id}}updateBoard()}))},updateBoard=function(instant){instant?processBoardHistory():options.history_refresh>0&&(reloadTimer&&stopUpdating(),reloadTimer=setTimeout(processBoardHistory,1e3*options.history_refresh))},stopUpdating=function(){clearTimeout(reloadTimer),reloadTimer=null},sortNotes=function(content,toggle){var desc,asc,sortCol=(0,_jquery.default)(content).parent().find(".mod_board_column_sort"),direction=(0,_jquery.default)(content).data("sort");if(direction||(direction=2==sortby?"desc":"asc"),toggle&&(direction="asc"==direction?"desc":"asc"),"asc"==direction?(sortCol.removeClass("fa-angle-down"),sortCol.addClass("fa-angle-up")):(sortCol.removeClass("fa-angle-up"),sortCol.addClass("fa-angle-down")),(0,_jquery.default)(content).data("sort",direction),1==sortby)desc=function(a,b){return(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(2==sortby)desc=function(a,b){return(0,_jquery.default)(b).find(".mod_board_rating").text()-(0,_jquery.default)(a).find(".mod_board_rating").text()||(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).find(".mod_board_rating").text()-(0,_jquery.default)(b).find(".mod_board_rating").text()||(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(3==sortby){let sortElements=(a,b)=>(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder");return void(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort(sortElements).appendTo((0,_jquery.default)(content))}(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort("asc"===direction?asc:desc).appendTo((0,_jquery.default)(content))},updateSortable=function(){let fromColumnID;(0,_jquery.default)(".board_column[data-locked='false'] .board_column_content").sortable({connectWith:".board_column[data-locked='false'] .board_column_content",cancel:".mod_board_nosort",handle:".move_note",start:function(_,ui){fromColumnID=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){var note=(0,_jquery.default)(ui.item),tocolumn=note.closest(".board_column"),elem=(0,_jquery.default)(this),noteid=note.data("ident"),columnid=tocolumn.data("ident");let sortorder=tocolumn.find(".board_column_content").children().index((0,_jquery.default)(".board_note[data-ident=".concat(noteid,"]")));moveNote(fromColumnID,{id:noteid,columnid:columnid,ownerid:ownerId,sortorder:sortorder},elem)}})};const moveNote=(fromColumnID,payload,elem)=>{updateSortOrders(fromColumnID,payload.columnid,payload.id,payload.sortorder),serviceCall("move_note",payload,(result=>{result.status?(lastHistoryId=result.historyid,updateNoteAria(payload.id),updateBoard(),sortNotes((0,_jquery.default)(".board_column[data-ident=".concat(payload.columnid,"] .board_column_content")))):elem&&elem.sortable("cancel")}))},columnSorting=()=>{let movingColumnId;(0,_jquery.default)(".mod_board").sortable({connectWith:".mod_board",axis:"x",containment:".mod_board_wrapper",cancel:".mod_board_nosort",handle:".mod_column_move",start:function(_,ui){movingColumnId=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){let column=(0,_jquery.default)(ui.item),sortorder=(0,_jquery.default)(".mod_board").find(".board_column").index(column);moveColumn({id:movingColumnId,sortorder:sortorder})}})},moveColumn=payload=>{serviceCall("move_column",payload,!1)},updateSortOrders=(fromColumnID,toColumnID,noteID,newSortOrder)=>{let toColumn=(0,_jquery.default)(".board_column[data-ident=".concat(toColumnID,"] .board_column_content")),movedNote=(0,_jquery.default)(".board_note[data-ident=".concat(noteID,"]")),oldSortOrder=movedNote.data("sortorder"),toChildren=toColumn.children();if(fromColumnID==toColumnID)toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");oldSortOrder=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1):oldSortOrder>newSortOrder&&sortOrder>=newSortOrder&&sortOrder<=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)}));else{let fromChildren=(0,_jquery.default)(".board_column[data-ident=".concat(fromColumnID,"] .board_column_content")).children();toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>=newSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)})),fromChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1)}))}movedNote.data("sortorder",newSortOrder)};var getBody=function(noteid,columnid,ownerId){var params={noteid:noteid,columnid:columnid,ownerid:ownerId};return _fragment.default.loadFragment("mod_board","note_form",contextid,params)},showModalForm=function(note){let title,noteId=0,columnId=note.data("column"),columnIdentifier=(0,_jquery.default)(".board_column[data-ident="+columnId+"]").find(".mod_board_column_name").text();note.data("ident")?(noteId=note.data("ident"),title=strings.modal_title_edit.replace("{column}",columnIdentifier)):title=strings.modal_title_new.replace("{column}",columnIdentifier),_modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:title,body:getBody(noteId,columnId,ownerId),large:!0,removeOnClose:!0}).then((function(modal){return modal.getBodyPromise().then((function(){let saveInProgress=!1;editModal=modal,modal.setLarge(),modal.setSaveButtonText(strings.post_button_text),modal.setButtonText("cancel",strings.cancel_button_text),modal.getRoot().on(_modal_events.default.hidden,(function(){stopNoteEdit(),note.data("ident")||note.remove()})),modal.getRoot().on(_modal_events.default.save,(function(e){e.preventDefault(),modal.getRoot().find("form").submit()}));var changeEvent=document.createEvent("HTMLEvents");if(changeEvent.initEvent("change",!0,!0),modal.getRoot().on("submit","form",(function(e){if(e.preventDefault(),saveInProgress)return;if(saveInProgress=!0,modal.getRoot().find("form").get(0).reportValidity()){modal.getRoot().find(":input").each((function(index,element){element.dispatchEvent(changeEvent)}));var invalid=_jquery.default.merge(modal.getRoot().find('[aria-invalid="true"]'),modal.getRoot().find(".error"),modal.getRoot().find(":invalid"));if(invalid.length)return invalid.first().focus(),void(saveInProgress=!1);var formData=JSON.stringify(modal.getRoot().find("form").serialize());serviceCall("submit_form",{contextid:contextid,jsonformdata:formData},(function(result){result.status?("insert"==result.action?(lastHistoryId=result.historyid,note.remove(),addNote(columnId,result.note.id,result.note.heading,result.note.content,{type:result.note.type,info:result.note.info,url:result.note.url},{id:result.note.userid},result.note.timecreated,result.note.rating),sortNotes((0,_jquery.default)(".board_column[data-ident="+columnId+"] .board_column_content")),updateNoteAria(result.note.id)):(lastHistoryId=result.historyid,getNoteTextForNote(note).html(result.note.content),getNoteHeadingForNote(note).html(result.note.heading),updateNoteAria(result.note.id),setAttachment(note,{type:result.note.type,info:result.note.info,url:result.note.url})),stopNoteEdit(),Y.use("moodle-core-formchangechecker",(function(){M.core_formchangechecker.reset_form_dirty_state()})),modal.destroy()):modal.destroy()}))}else saveInProgress=!1})),1==mediaSelection){modal.getRoot().find("#fitem_id_mediatype").hide();let mediaSelect=modal.getRoot().find("#fitem_id_mediatype select"),ytButton=modal.getRoot().find(".mod_board_attachment_button.youtube_button"),pictureButton=modal.getRoot().find(".mod_board_attachment_button.image_button"),linkButton=modal.getRoot().find(".mod_board_attachment_button.link_button"),updateMediaButtons=function(){switch(ytButton.removeClass("selected"),pictureButton.removeClass("selected"),linkButton.removeClass("selected"),mediaSelect.val()){case"1":ytButton.addClass("selected");break;case"2":pictureButton.addClass("selected");break;case"3":linkButton.addClass("selected")}};updateMediaButtons(),handleAction(ytButton,(function(){"1"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(1),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(pictureButton,(function(){"2"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(2),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(linkButton,(function(){"3"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(3),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)}))}else modal.getRoot().find("#fitem_id_mediabuttons").hide();return function(note,modal){let addYoutube,addImage,addLink,postButton,cancelButton,columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text(),modalRoot=modal.getRoot();if(note.data("ident")){var noteIdentifier=textIdentifierForNote(note);postButton=strings.aria_postedit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),cancelButton=strings.aria_canceledit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addYoutube=strings.aria_addmedia.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addImage=strings.aria_addmedia.replace("{type}",strings.option_image).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addLink=strings.aria_addmedia.replace("{type}",strings.option_link).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)}else postButton=strings.aria_postnew.replace("{column}",columnIdentifier),cancelButton=strings.aria_cancelnew.replace("{column}",columnIdentifier),addYoutube=strings.aria_addmedianew.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier),addImage=strings.aria_addmedianew.replace("{type}",strings.option_image).replace("{column}",columnIdentifier),addLink=strings.aria_addmedianew.replace("{type}",strings.option_link).replace("{column}",columnIdentifier);1==mediaSelection&&(modalRoot.find(".mod_board_attachment_button.youtube_button").attr("aria-label",addYoutube),modalRoot.find(".mod_board_attachment_button.youtube_button").attr("title",addYoutube),modalRoot.find(".mod_board_attachment_button.image_button").attr("aria-label",addImage),modalRoot.find(".mod_board_attachment_button.image_button").attr("title",addImage),modalRoot.find(".mod_board_attachment_button.link_button").attr("aria-label",addLink),modalRoot.find(".mod_board_attachment_button.link_button").attr("title",addLink));let button=modalRoot.find(modal.getActionSelector("save"));button&&button.attr("aria-label",postButton),button=modalRoot.find(modal.getActionSelector("cancel")),button&&button.attr("aria-label",cancelButton)}(note,modal),modal.show(),modal})).catch(_notification.default.exception),modal})).catch(_notification.default.exception)},fullScreenNote=(ident,notecontent)=>{const heading=getNoteHeadingForNote(notecontent).html(),modalBody=(0,_jquery.default)(document.createElement("div"));modalBody.addClass("mod_board_note_content");const text=getNoteTextForNote(notecontent);text&&modalBody.append(text.clone());const preview=(note=notecontent,(0,_jquery.default)(note).find(".mod_board_preview"));var note;preview&&modalBody.append(preview.clone());const commentArea=(0,_jquery.default)(document.createElement("div"));commentArea.attr("data-region","comment-area"),modalBody.append(commentArea),_comments.default.fetchFor(ident,commentArea),_modal_factory.default.create({type:_modal_factory.default.types.CANCEL,title:heading,body:modalBody}).then((function(modal){return modal.setLarge(),modal.show(),modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal}),this).catch(_notification.default.exception)},init=function(){serviceCall("get_board",{id:board.id,ownerid:ownerId},(function(columns){if(columns)for(var index in columns)addColumn(columns[index].id,columns[index].name,columns[index].locked,columns[index].notes||{},options.colours[columns[index].id%options.colours.length]);var column,newBusy;isEditor&&(column=(0,_jquery.default)('
'),newBusy=!1,column.append('
'),handleAction(column.find(".newcolumn"),(function(){newBusy||(newBusy=!0,serviceCall("add_column",{boardid:board.id,name:strings.default_column_heading},(function(result){addColumn(result.id,strings.default_column_heading,!1,{},selectHeadingColour()),lastHistoryId=result.historyid,newBusy=!1}),(function(){newBusy=!1})))})),(0,_jquery.default)(".mod_board").append(column)),lastHistoryId=board.historyid,isEditor&&(updateSortable(),columnSorting()),updateBoard()}))},stringsInfo=[];for(var string in strings)stringsInfo.push({key:string,component:"mod_board"});_jquery.default.when((0,_str.get_strings)(stringsInfo)).done((function(results){var index=0;for(string in strings)strings[string]=results[index++];init()}))},_jquery=_interopRequireDefault(_jquery),_ajax=_interopRequireDefault(_ajax),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_fragment=_interopRequireDefault(_fragment),_comments=_interopRequireDefault(_comments),_movenotesdialog=_interopRequireDefault(_movenotesdialog),_movecolumnsdialog=_interopRequireDefault(_movecolumnsdialog);const isAriaTriggerKey=function(key){return 13==key||32==key},encodeText=function(rawText){return(0,_jquery.default)("
").text(rawText).html()},decodeText=function(encodedText){return(0,_jquery.default)("
").html(encodedText).text()},handleAction=function(elem,callback){return elem.on("click keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode))return;e.preventDefault()}callback(),e.preventDefault()}))};return _exports.default})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=function(settings){var strings={default_column_heading:"",post_button_text:"",cancel_button_text:"",remove_note_title:"",remove_note_text:"",remove_column_title:"",note_changed_title:"",note_changed_text:"",note_deleted_text:"",rate_note_title:"",rate_note_text:"",rate_remove_note_text:"",Ok:"",delete:"",Cancel:"",warning:"",modal_title_new:"",modal_title_edit:"",option_youtube:"",option_image:"",option_link:"",aria_newcolumn:"",aria_newpost:"",aria_deletecolumn:"",aria_movecolumn:"",aria_deletepost:"",aria_movepost:"",aria_editpost:"",aria_addmedia:"",aria_addmedianew:"",aria_deleteattachment:"",aria_postedit:"",aria_canceledit:"",aria_postnew:"",aria_cancelnew:"",aria_ratepost:"",invalid_file_extension:"",invalid_file_size_min:"",invalid_file_size_max:"",invalid_youtube_url:""},options=JSON.parse(settings.settings)||{},board=options.board||{},contextid=options.contextid;var reloadTimer=null,lastHistoryId=null,isEditor=options.isEditor||!1,usersCanEdit=options.usersCanEdit,userId=parseInt(options.userId)||-1,userFirstname=options.firstname,userLastname=options.lastname,ownerId=parseInt(options.ownerId),mediaSelection=options.mediaselection||1,editingNote=0,isReadOnlyBoard=options.readonly||!1,showauthorofnote=options.showauthorofnote||!1,ratingenabled=options.ratingenabled,sortby=options.sortby||1,editModal=null,enableblanktarget=1===parseInt(options.enableblanktarget),serviceCall=function(method,args,callback,failcallback){"board_history"!==method&&stopUpdating(),function(method,args,callback,failcallback){_ajax.default.call([{methodname:"mod_board_"+method,args:args,done:function(data){callback(data)},fail:function(error){_notification.default.exception(error),failcallback&&failcallback(error)}}])}(method,args,(function(){callback&&callback.apply(null,arguments),"board_history"!==method&&"get_board"!=method&&updateBoard(!0)}),failcallback)},getNote=function(ident){return(0,_jquery.default)(".board_note[data-ident='"+ident+"']")},getNoteTextForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_text")},getNoteHeadingForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_heading")},getNoteBorderForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_border")},getNoteAttachmentsForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_attachment")},textIdentifierForNote=function(note){var noteText=getNoteTextForNote(note).html(),noteHeading=getNoteHeadingForNote(note).html(),noteAttachment=attachmentDataForNote(note);return noteHeading.length>0?noteHeading:noteText.length>0?noteText.replace(//gi," ").replace(/\n/g," ").split(/\s+/).slice(0,5).join(" "):noteAttachment.info&¬eAttachment.info.length>0?noteAttachment.info:null},updateNoteAria=function(noteId){var note=getNote(noteId),columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text();if(noteId){var noteIdentifier=textIdentifierForNote(note),deleteNoteString=strings.aria_deletepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier);note.find(".delete_note").attr("aria-label",deleteNoteString).attr("title",deleteNoteString);var moveNoteString=strings.aria_movepost.replace("{post}",noteIdentifier);note.find(".move_note").attr("aria-label",moveNoteString).attr("title",moveNoteString);var editNoteString=strings.aria_editpost.replace("{post}",noteIdentifier);note.find(".edit_note").attr("aria-label",editNoteString).attr("title",editNoteString),note.find(".mod_board_rating").attr("aria-label",strings.aria_ratepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)),note.find(".note_ariatext").html(noteIdentifier)}},updateColumnAria=function(columnId){var column=(0,_jquery.default)(".board_column[data-ident="+columnId+"]"),columnIdentifier=column.find(".mod_board_column_name").text(),newNoteString=strings.aria_newpost.replace("{column}",columnIdentifier),moveColumnString=strings.aria_movecolumn.replace("{column}",columnIdentifier),deleteColumnString=strings.aria_deletecolumn.replace("{column}",columnIdentifier);column.find(".newnote").attr("aria-label",newNoteString).attr("title",newNoteString),column.find(".mod_column_move").attr("aria-label",moveColumnString).attr("title",moveColumnString),column.find(".delete_column").attr("aria-label",deleteColumnString).attr("title",deleteColumnString),column.find(".board_note").each((function(index,note){updateNoteAria((0,_jquery.default)(note).data("ident"))}))},stopNoteEdit=function(){if(editingNote){var note=getNote(editingNote);if(note){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())}editingNote=0}else getNote(0).remove()};const sortAfterDelete=(columnID,sortorder)=>{let column=(columnID=>(0,_jquery.default)(".board_column[data-ident='".concat(columnID,"'] .board_column_content")))(columnID);column.children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so-1)}))};var setAttachment=function(note,attachment){var noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment){attachment?attachment.type+="":attachment={type:"0"};var attType=noteAttachment.find(".mod_board_type");attType.val(attachment.type?attachment.type:"0"),attType.val()>"0"&&(noteAttachment.find(".info").val(decodeText(attachment.info)),noteAttachment.find(".url").val(decodeText(attachment.url))),function(note){var noteAttachment=getNoteAttachmentsForNote(note),type=noteAttachment.find(".mod_board_type").val(),attachmentInfo=noteAttachment.find(".info"),attachmentUrl=noteAttachment.find(".url"),attachmentFile=noteAttachment.find(".mod_board_file");type>"0"?(attachmentInfo.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_info"]),attachmentUrl.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_url"]),attachmentInfo.show(),2==type&&FileReader?(attachmentFile.show(),attachmentUrl.hide()):(attachmentFile.hide(),attachmentUrl.show())):(attachmentInfo.hide(),attachmentUrl.hide(),attachmentFile.hide(),attachmentInfo.val(""),attachmentUrl.val(""))}(note)}previewAttachment(note,attachment)},attachmentDataForNote=function(note){var attachment={type:0,info:null,url:null,filename:null,filecontents:null},noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment.length){attachment.type=noteAttachment.find(".mod_board_type").val(),attachment.info=encodeText(noteAttachment.find(".info").val()),attachment.url=encodeText(noteAttachment.find(".url").val());var fileElem=noteAttachment.find(".mod_board_file>input");fileElem.data("filename")&&(attachment.filename=fileElem.data("filename"),attachment.filecontents=fileElem.data("filecontents"))}return attachment.info&&attachment.info.length||attachment.url&&attachment.url.length||attachment.filename||(attachment.type=0),attachment},attachmentTypeToString=function(type){switch(type){case"1":return"youtube";case"2":return"image";case"3":return"link";default:return null}};var previewAttachment=function(note,attachment){var elem=note.find(".mod_board_preview");if(attachment||(attachment=attachmentDataForNote(note)),getNoteTextForNote(note).html().length?elem.removeClass("mod_board_notext"):elem.addClass("mod_board_notext"),elem.removeClass("wrapper_youtube"),elem.removeClass("wrapper_image"),elem.removeClass("wrapper_url"),attachment.filename&&2==parseInt(attachment.type))elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();else if(attachment.url){const blanktarget=enableblanktarget?' target="_blank"':"";switch(parseInt(attachment.type)){case 1:{let url=(url=>{let videoID=url.match(/(\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/);return videoID&&void 0!==videoID[2]&&11===videoID[2].length?"https://www.youtube-nocookie.com/embed/".concat(videoID[2]):null})(attachment.url);null===url?elem.html(strings.invalid_youtube_url):(elem.html(''),elem.addClass("wrapper_youtube").addClass("position-relative")),elem.show()}break;case 2:elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();break;case 3:elem.html('"+(attachment.info||attachment.url)+""),elem.addClass("wrapper_url"),elem.show();break;default:elem.html(""),elem.hide()}}else elem.html(""),elem.hide()},addNote=function(columnid,ident,heading,content,attachment,owner,sortorder,rating){var ismynote=owner.id==userId||!ident,iseditable=isEditor||ismynote&&!isReadOnlyBoard;if(!ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}if(3==sortby){(0,_jquery.default)(".board_column[data-ident='".concat(columnid,"'] .board_column_content")).children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>=parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so+1)}))}var note=(0,_jquery.default)('
');ismynote&¬e.addClass("mod_board_mynote"),iseditable&¬e.addClass("mod_board_editablenote"),ismynote||iseditable||note.addClass("mod_board_nosort");var notecontent=(0,_jquery.default)('
'),notecontrols=(0,_jquery.default)('
'),noteHeading=(0,_jquery.default)('
'+(heading||"")+"
"),noteAuthorusername=(0,_jquery.default)(""),noteBorder=(0,_jquery.default)('
'),noteText=(0,_jquery.default)('
'+(content||"")+"
"),noteAriaText=(0,_jquery.default)(''),attachmentPreview=(0,_jquery.default)('
');if(showauthorofnote){let firstname="",lastname="";ismynote?(firstname=userFirstname,lastname=userLastname):(firstname=owner.firstname,lastname=owner.lastname),noteAuthorusername='
'+firstname+''+lastname+"
"}notecontent.append(noteHeading),notecontent.append(noteAuthorusername),notecontent.append(noteBorder),notecontent.append(noteText),notecontent.append(noteAriaText),notecontent.append(attachmentPreview),note.append(notecontent);var columnContent=(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_content"),beginEdit=()=>{!function(ident){if(editingNote){if(editingNote==ident)return;stopNoteEdit()}if(ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}var note=getNote(ident);note&&(showModalForm(note),ident&&(editingNote=ident))}(ident)};if(ident){if(ratingenabled){note.addClass("mod_board_rateablenote");var rateElement=(0,_jquery.default)('
'.concat(rating,"
"));handleAction(rateElement,(()=>{!function(ident){if(ratingenabled&&!isReadOnlyBoard){var note=getNote(ident),rating=note.find(".mod_board_rating");rating.data("disabled")||(rating.data("disabled",!0),serviceCall("can_rate_note",{id:ident},(function(result){if(result.canrate){const rateRemoveText=result.hasrated?strings.rate_remove_note_text:strings.rate_note_text;_notification.default.confirm(strings.rate_note_title,rateRemoveText,strings.Ok,strings.Cancel,(function(){serviceCall("rate_note",{id:ident},(function(result){result.status&&(lastHistoryId=result.historyid,rating.html(" ".concat(result.rating," ")),2==sortby&&sortNotes(note.closest(".board_column_content"))),rating.data("disabled",!1)}))})).then((function(rateModal){rateModal.getRoot().on(_modal_events.default.hidden,(function(){rating.data("disabled",!1)}))}))}})))}}(ident)})),notecontrols.append(rateElement)}if(iseditable){var removeElement=(0,_jquery.default)('
');if(handleAction(removeElement,(()=>{!function(ident){_notification.default.confirm(strings.remove_note_title,strings.remove_note_text,strings.delete,strings.Cancel,(function(){serviceCall("delete_note",{id:ident},(function(result){if(result.status){lastHistoryId=result.historyid;let note=getNote(ident);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}}))}))}(ident)})),notecontrols.append(removeElement),1==usersCanEdit||isEditor){var moveElement=(0,_jquery.default)('
');notecontrols.append(moveElement),_movenotesdialog.default.init(ownerId,moveNote)}var editElement=(0,_jquery.default)('
');notecontrols.append(editElement),handleAction(editElement,(()=>{beginEdit()})),updateSortable(),setAttachment(note,attachment)}else previewAttachment(note,attachment);note.append(notecontrols),handleAction(notecontent,(()=>fullScreenNote(ident,notecontent))),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide());var lastOne=columnContent.find(".board_note").last();lastOne.length?note.insertAfter(lastOne):columnContent.prepend(note)}else(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_newcontent").append(note),note.hide(),beginEdit()},addColumn=function(ident,name,locked,notes,colour){let headerStyle='style="border-top: 10px solid #'.concat(colour,'"');var iseditable=isEditor,nameCache=null,column=(0,_jquery.default)('
')),columnHeader=(0,_jquery.default)('
'),columnSort=(0,_jquery.default)('
'),columnName=(0,_jquery.default)('
'+name+"
"),columnContent=(0,_jquery.default)('
'),columnNewContent=(0,_jquery.default)('
');if(3!=sortby&&columnHeader.append(columnSort),columnHeader.append(columnName),options.hideheaders&&columnName.addClass("d-none"),columnSort.on("click",(function(){sortNotes(columnContent,!0)})),iseditable){column.addClass("mod_board_editablecolumn");const lockIcon=locked?"fa-lock":"fa-unlock",lockElement=(0,_jquery.default)('
')),lockstring=locked?"aria_column_locked":"aria_column_unlocked";(0,_str.get_string)(lockstring,"mod_board",name).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)})),handleAction(lockElement,(()=>{const lockColumn="true"!==column.attr("data-locked");serviceCall("lock_column",{id:ident,status:lockColumn},(function(result){const columnName=column.find(".mod_board_column_name").text();result.status&&(lockColumn?(lockElement.removeClass("fa-unlock").addClass("fa-lock"),column.attr("data-locked","true"),column.find(".board_button.newnote").addClass("d-none"),(0,_str.get_string)("aria_column_locked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))):(lockElement.removeClass("fa-lock").addClass("fa-unlock"),column.attr("data-locked","false"),column.find(".board_button.newnote").removeClass("d-none"),(0,_str.get_string)("aria_column_unlocked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))),lastHistoryId=result.historyid,updateSortable())}))})),columnHeader.append(lockElement),columnHeader.addClass("icon-size-3");const moveElement=(0,_jquery.default)('
');columnHeader.append(moveElement),_movecolumnsdialog.default.init(moveColumn);var removeElement=(0,_jquery.default)('
');handleAction(removeElement,(()=>{_notification.default.confirm(strings.remove_column_title,(0,_str.get_string)("remove_column_text","mod_board",getColumnName(ident)),strings.delete,strings.Cancel,(function(){serviceCall("delete_column",{id:ident},(function(result){result.status&&(column.remove(),lastHistoryId=result.historyid)}))}))})),columnHeader.append(removeElement)}if(column.append(columnHeader),column.append(columnContent),column.append(columnNewContent),iseditable&&(!function(elem,callback,callBeforeOnKeyEditing){if(elem.is(":editable"))throw new Error("handleEditableAction - must be called before setting the element as editable");elem.on("dblclick keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode)||elem.is(":editing"))return;if(e.preventDefault(),callBeforeOnKeyEditing&&callback(),elem.editable("open"),callBeforeOnKeyEditing)return}callback()}))}(columnName,(function(){nameCache=columnName.html()}),!0),columnName.editable({toggleFontSize:!1,closeOnEnter:!0,callback:function(data){data.content?serviceCall("update_column",{id:ident,name:columnName.html()},(function(result){result.status?(lastHistoryId=result.historyid,updateColumnAria(ident)):(columnName.html(nameCache),nameCache=null)}),(function(){columnName.html(nameCache),nameCache=null})):(columnName.html(nameCache),nameCache=null)}})),!isReadOnlyBoard){const newNoteButton=(0,_jquery.default)('
');columnNewContent.append(newNoteButton),"true"===column.attr("data-locked")&&newNoteButton.addClass("d-none"),handleAction(columnNewContent.find(".newnote"),(function(){addNote(ident,0,null,null,null,{id:userId},0,0)}))}var lastOne=(0,_jquery.default)(".mod_board .board_column_hasdata").last();if(lastOne.length?column.insertAfter(lastOne):(0,_jquery.default)(".mod_board").append(column),notes)for(var index in notes){let sortorder=3==sortby?notes[index].sortorder:notes[index].timecreated;addNote(ident,notes[index].id,notes[index].heading,notes[index].content,{type:notes[index].type,info:notes[index].info,url:notes[index].url},{id:notes[index].userid,firstname:notes[index].firstname,lastname:notes[index].lastname},sortorder,notes[index].rating)}sortNotes(columnContent),updateColumnAria(ident),(isEditor||1==usersCanEdit)&&updateSortable(),isEditor&&columnSorting()};const getColumnName=id=>(0,_jquery.default)(".board_column[data-ident='".concat(id,"']")).find(".mod_board_column_name").html();const selectHeadingColour=()=>{let colCount=(0,_jquery.default)(".board_column").length-1,colourCount=options.colours.length;return options.colours[colCount%colourCount]};var updateNote=function(note,heading,data){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteText.html(data.content),noteHeading.html(data.heading),setAttachment(note,data.attachment),updateNoteAria(data.id),noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())},processBoardHistory=function(){serviceCall("board_history",{id:board.id,ownerid:ownerId,since:lastHistoryId},(function(boardhistory){for(var index in boardhistory){var item=boardhistory[index];if(item.boardid==board.id){var data=JSON.parse(item.content);if("add_note"==item.action){let sortorder=3==sortby?data.sortorder:data.timecreated;addNote(data.columnid,data.id,data.heading,data.content,data.attachment,{id:item.userid},sortorder,data.rating),updateNoteAria(data.id),sortNotes((0,_jquery.default)(".board_column[data-ident="+data.columnid+"] .board_column_content"))}else if("update_note"==item.action){let note=getNote(data.id),formModal=editModal,historyData=data;if(note){getNoteHeadingForNote(note);editingNote==data.id?_notification.default.confirm(strings.note_changed_title,strings.note_changed_text,strings.Ok,strings.Cancel,(function(){formModal.hide(),updateNote(note,0,historyData),stopNoteEdit()})):updateNote(note,0,data)}}else if("delete_note"==item.action){editingNote==data.id&&(_notification.default.alert(strings.warning,strings.note_deleted_text),stopNoteEdit());let note=getNote(data.id);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}else if("add_column"==item.action)addColumn(data.id,data.name,!1,{},selectHeadingColour());else if("move_column"==item.action){const board=(0,_jquery.default)(".mod_board");data.sortorder.forEach((column=>{board.find(".board_column[data-ident='".concat(column,"']")).detach().appendTo(board)}))}else if("update_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"'] .mod_board_column_name").html(data.name),updateColumnAria(data.id);else if("lock_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").attr("data-locked",data.locked),data.locked?(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").addClass("d-none"):(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").removeClass("d-none"),updateSortable();else if("delete_column"==item.action){var column=(0,_jquery.default)(".board_column[data-ident='"+data.id+"']");editingNote&&column.find('.board_note[data-ident="'+editingNote+'"]').length&&stopNoteEdit(),column.remove()}else if("rate_note"==item.action){var note=getNote(data.id);note.find(".mod_board_rating").html(data.rating),2==sortby&&sortNotes(note.closest(".board_column_content"))}lastHistoryId=item.id}}updateBoard()}))},updateBoard=function(instant){instant?processBoardHistory():options.history_refresh>0&&(reloadTimer&&stopUpdating(),reloadTimer=setTimeout(processBoardHistory,1e3*options.history_refresh))},stopUpdating=function(){clearTimeout(reloadTimer),reloadTimer=null},sortNotes=function(content,toggle){var desc,asc,sortCol=(0,_jquery.default)(content).parent().find(".mod_board_column_sort"),direction=(0,_jquery.default)(content).data("sort");if(direction||(direction=2==sortby?"desc":"asc"),toggle&&(direction="asc"==direction?"desc":"asc"),"asc"==direction?(sortCol.removeClass("fa-angle-down"),sortCol.addClass("fa-angle-up")):(sortCol.removeClass("fa-angle-up"),sortCol.addClass("fa-angle-down")),(0,_jquery.default)(content).data("sort",direction),1==sortby)desc=function(a,b){return(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(2==sortby)desc=function(a,b){return(0,_jquery.default)(b).find(".mod_board_rating").text()-(0,_jquery.default)(a).find(".mod_board_rating").text()||(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).find(".mod_board_rating").text()-(0,_jquery.default)(b).find(".mod_board_rating").text()||(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(3==sortby){let sortElements=(a,b)=>(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder");return void(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort(sortElements).appendTo((0,_jquery.default)(content))}(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort("asc"===direction?asc:desc).appendTo((0,_jquery.default)(content))},updateSortable=function(){let fromColumnID;(0,_jquery.default)(".board_column[data-locked='false'] .board_column_content").sortable({connectWith:".board_column[data-locked='false'] .board_column_content",cancel:".mod_board_nosort",handle:".move_note",start:function(_,ui){fromColumnID=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){var note=(0,_jquery.default)(ui.item),tocolumn=note.closest(".board_column"),elem=(0,_jquery.default)(this),noteid=note.data("ident"),columnid=tocolumn.data("ident");let sortorder=tocolumn.find(".board_column_content").children().index((0,_jquery.default)(".board_note[data-ident=".concat(noteid,"]")));moveNote(fromColumnID,{id:noteid,columnid:columnid,ownerid:ownerId,sortorder:sortorder},elem)}})};const moveNote=(fromColumnID,payload,elem)=>{updateSortOrders(fromColumnID,payload.columnid,payload.id,payload.sortorder),serviceCall("move_note",payload,(result=>{result.status?(lastHistoryId=result.historyid,updateNoteAria(payload.id),updateBoard(),sortNotes((0,_jquery.default)(".board_column[data-ident=".concat(payload.columnid,"] .board_column_content")))):elem&&elem.sortable("cancel")}))},columnSorting=()=>{let movingColumnId;(0,_jquery.default)(".mod_board").sortable({connectWith:".mod_board",axis:"x",containment:".mod_board_wrapper",cancel:".mod_board_nosort",handle:".mod_column_move",start:function(_,ui){movingColumnId=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){let column=(0,_jquery.default)(ui.item),sortorder=(0,_jquery.default)(".mod_board").find(".board_column").index(column);moveColumn({id:movingColumnId,sortorder:sortorder})}})},moveColumn=payload=>{serviceCall("move_column",payload,!1)},updateSortOrders=(fromColumnID,toColumnID,noteID,newSortOrder)=>{let toColumn=(0,_jquery.default)(".board_column[data-ident=".concat(toColumnID,"] .board_column_content")),movedNote=(0,_jquery.default)(".board_note[data-ident=".concat(noteID,"]")),oldSortOrder=movedNote.data("sortorder"),toChildren=toColumn.children();if(fromColumnID==toColumnID)toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");oldSortOrder=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1):oldSortOrder>newSortOrder&&sortOrder>=newSortOrder&&sortOrder<=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)}));else{let fromChildren=(0,_jquery.default)(".board_column[data-ident=".concat(fromColumnID,"] .board_column_content")).children();toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>=newSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)})),fromChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1)}))}movedNote.data("sortorder",newSortOrder)};var getBody=function(noteid,columnid,ownerId){var params={noteid:noteid,columnid:columnid,ownerid:ownerId};return _fragment.default.loadFragment("mod_board","note_form",contextid,params)},showModalForm=function(note){let title,noteId=0,columnId=note.data("column"),columnIdentifier=(0,_jquery.default)(".board_column[data-ident="+columnId+"]").find(".mod_board_column_name").text();note.data("ident")?(noteId=note.data("ident"),title=strings.modal_title_edit.replace("{column}",columnIdentifier)):title=strings.modal_title_new.replace("{column}",columnIdentifier),_modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:title,body:getBody(noteId,columnId,ownerId),large:!0,removeOnClose:!0}).then((function(modal){return modal.getBodyPromise().then((function(){let saveInProgress=!1;editModal=modal,modal.setLarge(),modal.setSaveButtonText(strings.post_button_text),modal.setButtonText("cancel",strings.cancel_button_text),modal.getRoot().on(_modal_events.default.hidden,(function(){stopNoteEdit(),note.data("ident")||note.remove()})),modal.getRoot().on(_modal_events.default.save,(function(e){e.preventDefault(),modal.getRoot().find("form").submit()}));var changeEvent=document.createEvent("HTMLEvents");if(changeEvent.initEvent("change",!0,!0),modal.getRoot().on("submit","form",(function(e){if(e.preventDefault(),saveInProgress)return;if(saveInProgress=!0,modal.getRoot().find("form").get(0).reportValidity()){modal.getRoot().find(":input").each((function(index,element){element.dispatchEvent(changeEvent)}));var invalid=_jquery.default.merge(modal.getRoot().find('[aria-invalid="true"]'),modal.getRoot().find(".error"),modal.getRoot().find(":invalid"));if(invalid.length)return invalid.first().focus(),void(saveInProgress=!1);var formData=JSON.stringify(modal.getRoot().find("form").serialize());serviceCall("submit_form",{contextid:contextid,jsonformdata:formData},(function(result){result.status?("insert"==result.action?(lastHistoryId=result.historyid,note.remove(),addNote(columnId,result.note.id,result.note.heading,result.note.content,{type:result.note.type,info:result.note.info,url:result.note.url},{id:result.note.userid},result.note.timecreated,result.note.rating),sortNotes((0,_jquery.default)(".board_column[data-ident="+columnId+"] .board_column_content")),updateNoteAria(result.note.id)):(lastHistoryId=result.historyid,getNoteTextForNote(note).html(result.note.content),getNoteHeadingForNote(note).html(result.note.heading),updateNoteAria(result.note.id),setAttachment(note,{type:result.note.type,info:result.note.info,url:result.note.url})),stopNoteEdit(),Y.use("moodle-core-formchangechecker",(function(){M.core_formchangechecker.reset_form_dirty_state()})),modal.destroy()):modal.destroy()}))}else saveInProgress=!1})),1==mediaSelection){modal.getRoot().find("#fitem_id_mediatype").hide();let mediaSelect=modal.getRoot().find("#fitem_id_mediatype select"),ytButton=modal.getRoot().find(".mod_board_attachment_button.youtube_button"),pictureButton=modal.getRoot().find(".mod_board_attachment_button.image_button"),linkButton=modal.getRoot().find(".mod_board_attachment_button.link_button"),updateMediaButtons=function(){switch(ytButton.removeClass("selected"),pictureButton.removeClass("selected"),linkButton.removeClass("selected"),mediaSelect.val()){case"1":ytButton.addClass("selected");break;case"2":pictureButton.addClass("selected");break;case"3":linkButton.addClass("selected")}};updateMediaButtons(),handleAction(ytButton,(function(){"1"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(1),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(pictureButton,(function(){"2"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(2),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(linkButton,(function(){"3"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(3),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)}))}else modal.getRoot().find("#fitem_id_mediabuttons").hide();return function(note,modal){let addYoutube,addImage,addLink,postButton,cancelButton,columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text(),modalRoot=modal.getRoot();if(note.data("ident")){var noteIdentifier=textIdentifierForNote(note);postButton=strings.aria_postedit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),cancelButton=strings.aria_canceledit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addYoutube=strings.aria_addmedia.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addImage=strings.aria_addmedia.replace("{type}",strings.option_image).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addLink=strings.aria_addmedia.replace("{type}",strings.option_link).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)}else postButton=strings.aria_postnew.replace("{column}",columnIdentifier),cancelButton=strings.aria_cancelnew.replace("{column}",columnIdentifier),addYoutube=strings.aria_addmedianew.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier),addImage=strings.aria_addmedianew.replace("{type}",strings.option_image).replace("{column}",columnIdentifier),addLink=strings.aria_addmedianew.replace("{type}",strings.option_link).replace("{column}",columnIdentifier);1==mediaSelection&&(modalRoot.find(".mod_board_attachment_button.youtube_button").attr("aria-label",addYoutube),modalRoot.find(".mod_board_attachment_button.youtube_button").attr("title",addYoutube),modalRoot.find(".mod_board_attachment_button.image_button").attr("aria-label",addImage),modalRoot.find(".mod_board_attachment_button.image_button").attr("title",addImage),modalRoot.find(".mod_board_attachment_button.link_button").attr("aria-label",addLink),modalRoot.find(".mod_board_attachment_button.link_button").attr("title",addLink));let button=modalRoot.find(modal.getActionSelector("save"));button&&button.attr("aria-label",postButton),button=modalRoot.find(modal.getActionSelector("cancel")),button&&button.attr("aria-label",cancelButton)}(note,modal),modal.show(),modal})).catch(_notification.default.exception),modal})).catch(_notification.default.exception)},fullScreenNote=(ident,notecontent)=>{const heading=getNoteHeadingForNote(notecontent).html(),modalBody=(0,_jquery.default)(document.createElement("div"));modalBody.addClass("mod_board_note_content");const text=getNoteTextForNote(notecontent);text&&modalBody.append(text.clone());const preview=(note=notecontent,(0,_jquery.default)(note).find(".mod_board_preview"));var note;preview&&modalBody.append(preview.clone());const commentArea=(0,_jquery.default)(document.createElement("div"));commentArea.attr("data-region","comment-area"),modalBody.append(commentArea),_comments.default.fetchFor(ident,commentArea),_modal_factory.default.create({type:_modal_factory.default.types.CANCEL,title:heading,body:modalBody}).then((function(modal){return modal.setLarge(),modal.show(),modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal}),this).catch(_notification.default.exception)},init=function(){serviceCall("get_board",{id:board.id,ownerid:ownerId},(function(columns){if(columns)for(var index in columns)addColumn(columns[index].id,columns[index].name,columns[index].locked,columns[index].notes||{},options.colours[columns[index].id%options.colours.length]);var column,newBusy;isEditor&&(column=(0,_jquery.default)('
'),newBusy=!1,column.append('
'),handleAction(column.find(".newcolumn"),(function(){newBusy||(newBusy=!0,serviceCall("add_column",{boardid:board.id,name:strings.default_column_heading},(function(result){addColumn(result.id,strings.default_column_heading,!1,{},selectHeadingColour()),lastHistoryId=result.historyid,newBusy=!1}),(function(){newBusy=!1})))})),(0,_jquery.default)(".mod_board").append(column)),lastHistoryId=board.historyid,isEditor&&(updateSortable(),columnSorting()),updateBoard()}))},stringsInfo=[];for(var string in strings)stringsInfo.push({key:string,component:"mod_board"});_jquery.default.when((0,_str.get_strings)(stringsInfo)).done((function(results){var index=0;for(string in strings)strings[string]=results[index++];init()}))},_jquery=_interopRequireDefault(_jquery),_ajax=_interopRequireDefault(_ajax),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_fragment=_interopRequireDefault(_fragment),_comments=_interopRequireDefault(_comments),_movenotesdialog=_interopRequireDefault(_movenotesdialog),_movecolumnsdialog=_interopRequireDefault(_movecolumnsdialog);const isAriaTriggerKey=function(key){return 13==key||32==key},encodeText=function(rawText){return(0,_jquery.default)("
").text(rawText).html()},decodeText=function(encodedText){return(0,_jquery.default)("
").html(encodedText).text()},handleAction=function(elem,callback){return elem.on("click keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode))return;e.preventDefault()}callback(),e.preventDefault()}))};return _exports.default})); //# sourceMappingURL=board.min.js.map \ No newline at end of file diff --git a/amd/build/board.min.js.map b/amd/build/board.min.js.map index faece65..5ae6b4c 100755 --- a/amd/build/board.min.js.map +++ b/amd/build/board.min.js.map @@ -1 +1 @@ -{"version":3,"file":"board.min.js","sources":["../src/board.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle the board.\n *\n * @author Karen Holland \n * @copyrigt 2021 Brickfield Education Labs \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from \"jquery\";\nimport {get_strings as getStrings, get_string as getString} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport ModalFactory from \"core/modal_factory\";\nimport ModalEvents from \"core/modal_events\";\nimport Notification from \"core/notification\";\nimport \"mod_board/jquery.editable.amd\";\nimport \"mod_board/jquery.sortable.amd\";\nimport Fragment from \"core/fragment\";\nimport Comments from \"mod_board/comments\";\nimport moveNotesDialog from \"./movenotesdialog\";\nimport moveColumnsDialog from \"./movecolumnsdialog\";\n\n/**\n * Execute a ajax call to a mod_board ajax service.\n *\n * @param {string} method\n * @param {array} args\n * @param {method} callback\n * @param {method} failcallback\n * @private\n */\nconst _serviceCall = function(method, args, callback, failcallback) {\n Ajax.call([{\n methodname: 'mod_board_' + method,\n args: args,\n done: function(data) {\n callback(data);\n },\n fail: function(error) {\n Notification.exception(error);\n if (failcallback) {\n failcallback(error);\n }\n }\n }]);\n};\n\n/**\n * Indicates if this is a keycode we want to listend to for\n * aria purposes.\n *\n * @returns {boolean}\n * @param {number} key\n */\nconst isAriaTriggerKey = function(key) {\n return key == 13 || key == 32;\n};\n\n/**\n * Encodes text into html entities.\n *\n * @param {string} rawText\n * @returns {*|jQuery}\n */\nconst encodeText = function(rawText) {\n return $('
').text(rawText).html();\n};\n\n/**\n * Decodes text from html entities.\n *\n * @param {string} encodedText\n * @returns {*|jQuery}\n */\nconst decodeText = function(encodedText) {\n return $('
').html(encodedText).text();\n};\n\n/**\n * Handler for keypress and click actions.\n *\n * @param {object} elem\n * @param {function} callback\n * @returns {*}\n */\nconst handleAction = function(elem, callback) {\n return elem.on('click keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode)) {\n e.preventDefault();\n } else {\n return;\n }\n }\n\n callback();\n e.preventDefault();\n });\n};\n\n/**\n * Setting up element edibility.\n *\n * @param {object} elem\n * @param {function} callback\n * @param {function} callBeforeOnKeyEditing\n * @returns {*}\n */\nconst handleEditableAction = function(elem, callback, callBeforeOnKeyEditing) {\n if (elem.is(':editable')) {\n throw new Error('handleEditableAction - must be called before setting the element as editable');\n }\n\n // Can't use on(edit) here because we want to do actions (save cache) before the control goes into edit mode\n return elem.on('dblclick keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode) && !elem.is(':editing')) {\n e.preventDefault();\n if (callBeforeOnKeyEditing) {\n callback();\n }\n elem.editable('open');\n if (callBeforeOnKeyEditing) {\n return;\n }\n } else {\n return;\n }\n }\n\n callback();\n });\n};\n\n/**\n * The default function of the module, which does the setup of the page.\n *\n * @param {object} settings\n */\nexport default function(settings) {\n // An array of strings to load as a batch later.\n // Not necessary, but used to load all the strings in one ajax call.\n var strings = {\n default_column_heading: '',\n post_button_text: '',\n cancel_button_text: '',\n remove_note_title: '',\n remove_note_text: '',\n remove_column_title: '',\n note_changed_title: '',\n note_changed_text: '',\n note_deleted_text: '',\n rate_note_title: '',\n rate_note_text: '',\n rate_remove_note_text: '',\n Ok: '',\n delete: '',\n Cancel: '',\n warning: '',\n modal_title_new: '',\n modal_title_edit: '',\n option_youtube: '',\n option_image: '',\n option_link: '',\n\n aria_newcolumn: '',\n aria_newpost: '',\n aria_deletecolumn: '',\n aria_movecolumn: '',\n aria_deletepost: '',\n aria_movepost: '',\n aria_editpost: '',\n aria_addmedia: '',\n aria_addmedianew: '',\n aria_deleteattachment: '',\n aria_postedit: '',\n aria_canceledit: '',\n aria_postnew: '',\n aria_cancelnew: '',\n aria_ratepost: '',\n\n invalid_file_extension: '',\n invalid_file_size_min: '',\n invalid_file_size_max: '',\n\n invalid_youtube_url: '',\n };\n\n // Json decode the strings from the settings.\n var options = JSON.parse(settings.settings) || {};\n var board = options.board || {};\n var contextid = options.contextid;\n\n const MEDIA_SELECTION_BUTTONS = 1,\n ATTACHMENT_VIDEO = 1,\n ATTACHMENT_IMAGE = 2,\n ATTACHMENT_LINK = 3,\n SORTBY_DATE = 1,\n SORTBY_RATING = 2,\n SORTBY_NONE = 3;\n\n var reloadTimer = null,\n lastHistoryId = null,\n isEditor = options.isEditor || false,\n usersCanEdit = options.usersCanEdit,\n userId = parseInt(options.userId) || -1,\n ownerId = parseInt(options.ownerId),\n mediaSelection = options.mediaselection || MEDIA_SELECTION_BUTTONS,\n editingNote = 0,\n isReadOnlyBoard = options.readonly || false,\n ratingenabled = options.ratingenabled,\n sortby = options.sortby || SORTBY_DATE,\n editModal = null,\n enableblanktarget = (parseInt(options.enableblanktarget) === 1);\n\n /**\n * Helper method to make calls to mod_board external services.\n *\n * @param {string} method\n * @param {array} args\n * @param {function} callback\n * @param {function} failcallback\n */\n var serviceCall = function(method, args, callback, failcallback) {\n if (method !== 'board_history') {\n stopUpdating();\n }\n _serviceCall(method, args, function() {\n if (callback) {\n callback.apply(null, arguments);\n }\n if (method !== 'board_history' && method != 'get_board') {\n updateBoard(true);\n }\n }, failcallback);\n };\n\n /**\n * Returns the jquery element of a given note identifier.\n *\n * @param {number} ident\n * @returns {jQuery}\n */\n var getNote = function(ident) {\n return $(\".board_note[data-ident='\" + ident + \"']\");\n };\n\n /**\n * Returns the jquery element of the note text for the given note element.\n *\n * @method getNoteTextForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteTextForNote = function(note) {\n return $(note).find(\".mod_board_note_text\");\n };\n\n /**\n * Returns the jquery element of the preview for the given note element.\n *\n * @method getNotePreviewForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNotePreviewForNote = (note) => {\n return $(note).find(\".mod_board_preview\");\n };\n\n\n /**\n * Returns the jquery element of the note heading for the given note element.\n *\n * @method getNoteHeadingForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteHeadingForNote = function(note) {\n return $(note).find(\".mod_board_note_heading\");\n };\n\n /**\n * Returns the jquery element of the note border for the given note element.\n *\n * @method getNoteBorderForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteBorderForNote = function(note) {\n return $(note).find(\".mod_board_note_border\");\n };\n\n /**\n * Gets a jquery node for the attachments of a given note.\n *\n * @method getNoteAttachmentsForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteAttachmentsForNote = function(note) {\n return $(note).find(\".mod_board_note_attachment\");\n };\n\n /**\n * Creates text identifier for a given node.\n *\n * @method textIdentifierForNote\n * @param {object} note\n * @returns {null|*|jQuery}\n */\n var textIdentifierForNote = function(note) {\n var noteText = getNoteTextForNote(note).html(),\n noteHeading = getNoteHeadingForNote(note).html(),\n noteAttachment = attachmentDataForNote(note);\n\n if (noteHeading.length > 0) {\n return noteHeading;\n }\n if (noteText.length > 0) {\n return noteText.replace(//gi, \" \").replace(/\\n/g, \" \").split(/\\s+/).slice(0, 5).join(\" \");\n }\n if (noteAttachment.info && noteAttachment.info.length > 0) {\n return noteAttachment.info;\n }\n return null;\n };\n\n /**\n * Update the Aria info for a given note id.\n *\n * @method updateNoteAria\n * @param {number} noteId\n */\n var updateNoteAria = function(noteId) {\n var note = getNote(noteId),\n columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text();\n\n if (noteId) { // New post\n var noteIdentifier = textIdentifierForNote(note),\n deleteNoteString = strings.aria_deletepost.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n\n note.find('.delete_note').attr('aria-label', deleteNoteString).attr('title', deleteNoteString);\n\n var moveNoteString = strings.aria_movepost.replace('{post}', noteIdentifier);\n note.find('.move_note').attr('aria-label', moveNoteString).attr('title', moveNoteString);\n\n var editNoteString = strings.aria_editpost.replace('{post}', noteIdentifier);\n note.find('.edit_note').attr('aria-label', editNoteString).attr('title', editNoteString);\n\n note.find('.mod_board_rating').attr('aria-label', strings.aria_ratepost.replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier));\n note.find('.note_ariatext').html(noteIdentifier);\n }\n\n };\n\n /**\n * Update the Aria information for a given column id.\n *\n * @method updateColumnAria\n * @param {number} columnId\n */\n var updateColumnAria = function(columnId) {\n var column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n newNoteString = strings.aria_newpost.replace('{column}', columnIdentifier),\n moveColumnString = strings.aria_movecolumn.replace('{column}', columnIdentifier),\n deleteColumnString = strings.aria_deletecolumn.replace('{column}', columnIdentifier);\n column.find('.newnote').attr('aria-label', newNoteString).attr('title', newNoteString);\n column.find('.mod_column_move').attr('aria-label', moveColumnString).attr('title', moveColumnString);\n column.find('.delete_column').attr('aria-label', deleteColumnString).attr('title', deleteColumnString);\n\n column.find(\".board_note\").each(function(index, note) {\n updateNoteAria($(note).data('ident'));\n });\n };\n\n /**\n * Stop the current note editing process.\n *\n * @method stopNoteEdit\n */\n var stopNoteEdit = function() {\n if (!editingNote) {\n getNote(0).remove();\n return;\n }\n\n var note = getNote(editingNote);\n\n if (note) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n }\n\n editingNote = 0;\n };\n\n /**\n * Start the editing of a particular note, by identifier.\n *\n * @method startNoteEdit\n * @param {number} ident\n */\n var startNoteEdit = function(ident) {\n\n if (editingNote) {\n if (editingNote == ident) {\n return;\n }\n stopNoteEdit();\n }\n\n if (ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n var note = getNote(ident);\n if (note) {\n showModalForm(note);\n\n if (ident) {\n editingNote = ident;\n }\n }\n };\n\n /**\n * Delete a given note, by identifier.\n *\n * @method deleteNote\n * @param {number} ident\n */\n var deleteNote = function(ident) {\n Notification.confirm(\n strings.remove_note_title, // Are you sure?\n strings.remove_note_text, // This will effect others.\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_note', { id: ident }, function (result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n let note = getNote(ident);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n }\n });\n }\n );\n };\n\n /**\n * This function gets a board column as a jQuery element.\n * @param {number} columnID The column ID.\n * @returns {jQuery}\n */\n const getColumn = (columnID) => {\n return $(`.board_column[data-ident='${columnID}'] .board_column_content`);\n };\n\n const sortAfterDelete = (columnID, sortorder) => {\n let column = getColumn(columnID);\n let elements = column.children().filter((_, element) => {\n return parseInt($(element).data('sortorder')) > parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so - 1);\n });\n };\n\n /**\n * Rate (star) a give note, by identifier.\n *\n * @method rateNote\n * @param {number} ident\n */\n var rateNote = function(ident) {\n if (!ratingenabled) {\n return;\n }\n if (isReadOnlyBoard) {\n return;\n }\n\n var note = getNote(ident),\n rating = note.find('.mod_board_rating');\n if (rating.data('disabled')) {\n return;\n }\n rating.data('disabled', true);\n\n serviceCall('can_rate_note', {id: ident}, function(result) {\n if (result.canrate) {\n const rateRemoveText = result.hasrated ? strings.rate_remove_note_text : strings.rate_note_text;\n Notification.confirm(\n strings.rate_note_title,\n rateRemoveText, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n serviceCall('rate_note', {id: ident}, function(result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n rating.html(` ${result.rating} `);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n rating.data('disabled', false);\n });\n }\n ).then(function(rateModal) {\n // Do this here, because it catches both cancel clicks, or someone clicking the X.\n rateModal.getRoot().on(ModalEvents.hidden, function() {\n rating.data('disabled', false);\n });\n });\n }\n });\n };\n\n /**\n * Update the attachment information of a note.\n *\n * @method attachmentTypeChanged\n * @param {object} note\n */\n var attachmentTypeChanged = function(note) {\n var noteAttachment = getNoteAttachmentsForNote(note),\n type = noteAttachment.find('.mod_board_type').val(),\n attachmentInfo = noteAttachment.find('.info'),\n attachmentUrl = noteAttachment.find('.url'),\n attachmentFile = noteAttachment.find('.mod_board_file');\n\n if (type > \"0\") {\n attachmentInfo.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_info']);\n attachmentUrl.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_url']);\n\n attachmentInfo.show();\n if (type == ATTACHMENT_IMAGE && FileReader) {\n attachmentFile.show();\n attachmentUrl.hide();\n } else {\n attachmentFile.hide();\n attachmentUrl.show();\n }\n } else {\n attachmentInfo.hide();\n attachmentUrl.hide();\n attachmentFile.hide();\n\n attachmentInfo.val('');\n attachmentUrl.val('');\n\n }\n };\n\n /**\n * Set the attachment of a note.\n *\n * @method setAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var setAttachment = function(note, attachment) {\n var noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment) {\n if (!attachment) {\n attachment = {type: \"0\"};\n } else {\n attachment.type += \"\";// Just in case\n }\n var attType = noteAttachment.find('.mod_board_type');\n attType.val(attachment.type ? attachment.type : \"0\");\n if (attType.val() > \"0\") {\n noteAttachment.find('.info').val(decodeText(attachment.info));\n noteAttachment.find('.url').val(decodeText(attachment.url));\n }\n attachmentTypeChanged(note, attachment);\n }\n previewAttachment(note, attachment);\n };\n\n /**\n * Returns an object with various information about a note's attachment.\n *\n * @method attachmentDataForNote\n * @param {object} note\n * @returns {{filename: null, filecontents: null, type: number, url: null, info: null}}\n */\n var attachmentDataForNote = function(note) {\n var attachment = {type: 0, info: null, url: null, filename: null, filecontents: null},\n noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment.length) {\n attachment.type = noteAttachment.find('.mod_board_type').val();\n attachment.info = encodeText(noteAttachment.find('.info').val());\n attachment.url = encodeText(noteAttachment.find('.url').val());\n var fileElem = noteAttachment.find('.mod_board_file>input');\n if (fileElem.data('filename')) {\n attachment.filename = fileElem.data('filename');\n attachment.filecontents = fileElem.data('filecontents');\n }\n }\n if ((!attachment.info || !attachment.info.length) && (!attachment.url || !attachment.url.length) &&\n (!attachment.filename)) {\n attachment.type = 0;\n }\n\n return attachment;\n };\n\n /**\n * Get the string type of a attachment type number.\n *\n * @method attachmentTypeToString\n * @param {number} type\n * @returns {string|null}\n */\n var attachmentTypeToString = function(type) {\n switch (type) {\n case \"1\": return 'youtube';\n case \"2\": return 'image';\n case \"3\": return 'link';\n default: return null;\n }\n };\n\n /**\n * This parses a youtube video ID from a URL. We can use this ID to\n * construct the embed URL.\n * @param {string} url The URL entered to the modal.\n * @returns {string | null} The youtube embed URL or null.\n */\n const getEmbedUrl = (url) => {\n // Thanks for the regex from: https://gist.github.com/rodrigoborgesdeoliveira/987683cfbfcc8d800192da1e73adc486.\n let regex = /(\\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/;\n let videoID = url.match(regex);\n if (!videoID || videoID[2] === undefined || videoID[2].length !== 11) {\n return null;\n }\n return `https://www.youtube-nocookie.com/embed/${videoID[2]}`;\n };\n\n /**\n * Display the attachment preview for a note.\n *\n * @method previewAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var previewAttachment = function(note, attachment) {\n var elem = note.find('.mod_board_preview');\n if (!attachment) {\n attachment = attachmentDataForNote(note);\n }\n\n if (!getNoteTextForNote(note).html().length) {\n elem.addClass('mod_board_notext');\n } else {\n elem.removeClass('mod_board_notext');\n }\n\n elem.removeClass('wrapper_youtube');\n elem.removeClass('wrapper_image');\n elem.removeClass('wrapper_url');\n if (attachment.filename && parseInt(attachment.type) == ATTACHMENT_IMAGE) { // Before uploading\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n } else if (attachment.url) {\n const blanktarget = enableblanktarget ? ' target=\"_blank\"' : '';\n switch (parseInt(attachment.type)) {\n case ATTACHMENT_VIDEO: { // Youtube\n let url = getEmbedUrl(attachment.url);\n if (url === null) {\n elem.html(strings.invalid_youtube_url);\n } else {\n elem.html('');\n elem.addClass('wrapper_youtube').addClass('position-relative');\n }\n elem.show();\n }\n break;\n case ATTACHMENT_IMAGE: // Image\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n break;\n case ATTACHMENT_LINK: // Url\n elem.html('' +\n (attachment.info || attachment.url) + '');\n elem.addClass('wrapper_url');\n elem.show();\n break;\n default:\n elem.html('');\n elem.hide();\n }\n } else {\n elem.html('');\n elem.hide();\n }\n };\n\n /**\n * Add a new note with the given information.\n *\n * @method addNote\n * @param {number} columnid\n * @param {number} ident\n * @param {string} heading\n * @param {string} content\n * @param {object} attachment\n * @param {object} owner\n * @param {number} sortorder\n * @param {string} rating\n */\n var addNote = function(columnid, ident, heading, content, attachment, owner, sortorder, rating) {\n var ismynote = owner.id == userId || !ident;\n var iseditable = isEditor || (ismynote && !isReadOnlyBoard);\n\n if (!ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n // Making space for this note if necessary in the sort order.\n if (sortby == SORTBY_NONE) {\n let children = $(`.board_column[data-ident='${columnid}'] .board_column_content`).children();\n let elements = children.filter((_, element) => {\n return parseInt($(element).data('sortorder')) >= parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so + 1);\n });\n }\n\n var note = $('
');\n if (ismynote) {\n note.addClass('mod_board_mynote');\n }\n if (iseditable) {\n note.addClass('mod_board_editablenote');\n }\n if (!ismynote && !iseditable) {\n note.addClass('mod_board_nosort');\n }\n\n var notecontent = $('
'),\n notecontrols = $('
'),\n noteHeading = $('
' + (heading ? heading : '') + '
'),\n noteBorder = $('
'),\n noteText = $('
' + (content ? content : '') + '
'),\n noteAriaText = $('
'),\n attachmentPreview = $('
');\n\n notecontent.append(noteHeading);\n notecontent.append(noteBorder);\n notecontent.append(noteText);\n notecontent.append(noteAriaText);\n\n notecontent.append(attachmentPreview);\n note.append(notecontent);\n\n var columnContent = $('.board_column[data-ident=' + columnid + '] .board_column_content');\n\n var beginEdit = () => {\n startNoteEdit(ident);\n };\n\n if (ident) {\n if (ratingenabled) {\n note.addClass('mod_board_rateablenote');\n var rateElement = $(`
${rating}
`);\n\n handleAction(rateElement, () => {\n rateNote(ident);\n });\n notecontrols.append(rateElement);\n }\n\n if (iseditable) {\n var removeElement = $('
');\n handleAction(removeElement, () => {\n deleteNote(ident);\n });\n\n notecontrols.append(removeElement);\n\n if (usersCanEdit == 1 || isEditor) {\n var moveElement = $('
');\n notecontrols.append(moveElement);\n moveNotesDialog.init(ownerId, moveNote);\n }\n\n var editElement = $('
');\n notecontrols.append(editElement);\n handleAction(editElement, () => {\n beginEdit();\n });\n updateSortable();\n setAttachment(note, attachment);\n } else {\n previewAttachment(note, attachment);\n }\n\n note.append(notecontrols);\n\n handleAction(notecontent, () => fullScreenNote(ident, notecontent));\n\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n\n var lastOne = columnContent.find(\".board_note\").last();\n\n if (lastOne.length) {\n note.insertAfter(lastOne);\n } else {\n columnContent.prepend(note);\n }\n } else {\n $('.board_column[data-ident=' + columnid + '] .board_column_newcontent').append(note);\n // This is effectively a note placeholder. So we don't need to show it.\n note.hide();\n beginEdit();\n }\n };\n\n /**\n * Add a new column.\n *\n * @method addColumn\n * @param {object} ident\n * @param {string} name\n * @param {bool} locked\n * @param {array} notes\n * @param {string} colour\n */\n var addColumn = function(ident, name, locked, notes, colour) {\n let headerStyle = `style=\"border-top: 10px solid #${colour}\"`;\n var iseditable = isEditor,\n nameCache = null,\n column = $(`
`),\n columnHeader = $('
'),\n columnSort = $('
'),\n columnName = $('
' + name + '
'),\n columnContent = $('
'),\n columnNewContent = $('
');\n // Only add the sort button if it makes sense.\n if (sortby != SORTBY_NONE) {\n columnHeader.append(columnSort);\n }\n columnHeader.append(columnName);\n\n if (options.hideheaders) {\n columnName.addClass('d-none');\n }\n\n columnSort.on('click', function() {\n sortNotes(columnContent, true);\n });\n\n if (iseditable) {\n column.addClass('mod_board_editablecolumn');\n const lockIcon = locked ? 'fa-lock' : 'fa-unlock';\n const lockElement = $(`
`);\n const lockstring = locked ? 'aria_column_locked' : 'aria_column_unlocked';\n getString(lockstring, 'mod_board', name).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n\n handleAction(lockElement, () => {\n const lockColumn = column.attr('data-locked') !== 'true';\n serviceCall('lock_column', {id: ident, status: lockColumn}, function(result) {\n const columnName = column.find('.mod_board_column_name').text();\n if (result.status) {\n if (lockColumn) {\n lockElement.removeClass('fa-unlock').addClass('fa-lock');\n column.attr('data-locked', 'true');\n column.find('.board_button.newnote').addClass('d-none');\n getString('aria_column_locked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n } else {\n lockElement.removeClass('fa-lock').addClass('fa-unlock');\n column.attr('data-locked', 'false');\n column.find('.board_button.newnote').removeClass('d-none');\n getString('aria_column_unlocked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n }\n lastHistoryId = result.historyid;\n updateSortable();\n }\n });\n });\n columnHeader.append(lockElement);\n\n columnHeader.addClass('icon-size-3');\n const moveElement = $('
');\n columnHeader.append(moveElement);\n moveColumnsDialog.init(moveColumn);\n var removeElement = $('
');\n handleAction(removeElement, () => {\n Notification.confirm(\n strings.remove_column_title, // Are you sure?\n getString('remove_column_text', 'mod_board', getColumnName(ident)),\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_column', {id: ident}, function(result) {\n if (result.status) {\n column.remove();\n lastHistoryId = result.historyid;\n }\n });\n }\n );\n });\n\n columnHeader.append(removeElement);\n }\n\n column.append(columnHeader);\n column.append(columnContent);\n column.append(columnNewContent);\n\n if (iseditable) {\n handleEditableAction(columnName, function() {\n nameCache = columnName.html();\n }, true);\n\n columnName.editable({\n toggleFontSize: false,\n closeOnEnter: true,\n callback: function(data) {\n if (data.content) {\n serviceCall('update_column', {id: ident, name: columnName.html()}, function(result) {\n if (!result.status) {\n columnName.html(nameCache);\n nameCache = null;\n } else {\n lastHistoryId = result.historyid;\n updateColumnAria(ident);\n }\n }, function() {\n columnName.html(nameCache);\n nameCache = null;\n });\n } else {\n columnName.html(nameCache);\n nameCache = null;\n }\n }\n });\n }\n\n if (!isReadOnlyBoard) {\n const newNoteButton = $('
' +\n '
');\n columnNewContent.append(newNoteButton);\n if (column.attr('data-locked') === 'true') {\n newNoteButton.addClass('d-none');\n }\n handleAction(columnNewContent.find('.newnote'), function() {\n addNote(ident, 0, null, null, null, {id: userId}, 0, 0);\n });\n }\n\n var lastOne = $(\".mod_board .board_column_hasdata\").last();\n if (lastOne.length) {\n column.insertAfter(lastOne);\n } else {\n $(\".mod_board\").append(column);\n }\n\n if (notes) {\n for (var index in notes) {\n let sortorder = sortby == 3 ? notes[index].sortorder : notes[index].timecreated;\n addNote(ident, notes[index].id, notes[index].heading, notes[index].content,\n {type: notes[index].type, info: notes[index].info, url: notes[index].url},\n {id: notes[index].userid}, sortorder, notes[index].rating);\n }\n }\n sortNotes(columnContent);\n updateColumnAria(ident);\n if (isEditor || usersCanEdit == 1) {\n updateSortable();\n }\n if (isEditor) {\n columnSorting();\n }\n };\n\n /**\n * Gets the text name used in the heading of a column.\n * @param {number} id The ID data attribute on the column element.\n * @returns {string}\n */\n const getColumnName = (id) => {\n return $(`.board_column[data-ident='${id}']`).find('.mod_board_column_name').html();\n };\n\n /**\n * Add the new column button.\n *\n * @method addNewColumnButton\n */\n var addNewColumnButton = function() {\n var column = $('
'),\n newBusy = false;\n column.append('
');\n\n handleAction(column.find('.newcolumn'), function() {\n if (newBusy) {\n return;\n }\n newBusy = true;\n\n serviceCall('add_column', {boardid: board.id, name: strings.default_column_heading}, function(result) {\n addColumn(result.id, strings.default_column_heading, false, {}, selectHeadingColour());\n lastHistoryId = result.historyid;\n newBusy = false;\n }, function() {\n newBusy = false;\n });\n });\n\n $(\".mod_board\").append(column);\n };\n\n /**\n * This selects the next heading colour from options based on the count of the\n * current columns. Length of decremented by one as the new column button is\n * also denoted as a column.\n * @returns {string} colour hex string.\n */\n const selectHeadingColour = () => {\n let colCount = $('.board_column').length - 1;\n let colourCount = options.colours.length;\n return options.colours[colCount % colourCount];\n };\n\n /**\n * Update a note with the provided information.\n *\n * @method updateNote\n * @param {object} note\n * @param {string} heading\n * @param {object} data\n */\n var updateNote = function(note, heading, data) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n noteText.html(data.content);\n noteHeading.html(data.heading);\n setAttachment(note, data.attachment);\n updateNoteAria(data.id);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n };\n\n /**\n * Fetch and process the recent board history.\n *\n * @method processBoardHistory\n */\n var processBoardHistory = function() {\n serviceCall('board_history', {id: board.id, ownerid: ownerId, since: lastHistoryId}, function(boardhistory) {\n for (var index in boardhistory) {\n var item = boardhistory[index];\n if (item.boardid != board.id) {\n continue; // Hmm\n }\n\n var data = JSON.parse(item.content);\n if (item.action == 'add_note') {\n let sortorder = sortby == 3 ? data.sortorder : data.timecreated;\n addNote(data.columnid, data.id, data.heading, data.content, data.attachment,\n {id: item.userid}, sortorder, data.rating);\n updateNoteAria(data.id);\n sortNotes($('.board_column[data-ident=' + data.columnid + '] .board_column_content'));\n } else if (item.action == 'update_note') {\n let note = getNote(data.id),\n formModal = editModal,\n historyData = data;\n if (note) {\n let noteHeading = getNoteHeadingForNote(note);\n\n if (editingNote == data.id) {\n Notification.confirm(\n strings.note_changed_title, // Confirm.\n strings.note_changed_text, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n formModal.hide();\n updateNote(note, noteHeading, historyData);\n stopNoteEdit();\n }\n );\n } else {\n updateNote(note, noteHeading, data);\n }\n }\n } else if (item.action == 'delete_note') {\n if (editingNote == data.id) {\n Notification.alert(strings.warning, strings.note_deleted_text);\n stopNoteEdit();\n }\n let note = getNote(data.id);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n\n } else if (item.action == 'add_column') {\n addColumn(data.id, data.name, false, {}, selectHeadingColour());\n } else if (item.action == 'move_column') {\n const board = $('.mod_board');\n data.sortorder.forEach(column => {\n const columnElement = board.find(`.board_column[data-ident='${column}']`);\n columnElement.detach().appendTo(board);\n });\n } else if (item.action == 'update_column') {\n $(\".board_column[data-ident='\" + data.id + \"'] .mod_board_column_name\").html(data.name);\n updateColumnAria(data.id);\n } else if (item.action == 'lock_column') {\n $(\".board_column[data-ident='\" + data.id + \"']\").attr(\"data-locked\", data.locked);\n if (data.locked) {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').addClass('d-none');\n } else {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').removeClass('d-none');\n }\n updateSortable();\n } else if (item.action == 'delete_column') {\n var column = $(\".board_column[data-ident='\" + data.id + \"']\");\n if (editingNote && column.find('.board_note[data-ident=\"' + editingNote + '\"]').length) {\n stopNoteEdit();\n }\n column.remove();\n } else if (item.action == 'rate_note') {\n var note = getNote(data.id);\n note.find('.mod_board_rating').html(data.rating);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n lastHistoryId = item.id;\n }\n\n updateBoard();\n });\n };\n\n /**\n * Trigger a board update.\n *\n * @method updateBoard\n * @param {boolean} instant\n */\n var updateBoard = function(instant) {\n if (instant) {\n processBoardHistory();\n } else if (options.history_refresh > 0) {\n if (reloadTimer) {\n stopUpdating();\n }\n reloadTimer = setTimeout(processBoardHistory, options.history_refresh * 1000);\n }\n };\n\n /**\n * Stop/prevent the board reload timer from firing.\n *\n * @method stopUpdating\n */\n var stopUpdating = function() {\n clearTimeout(reloadTimer);\n reloadTimer = null;\n };\n\n /**\n * Sort a set of notes.\n *\n * @sortNotes\n * @param {string} content\n * @param {boolean} toggle\n */\n var sortNotes = function(content, toggle) {\n var sortCol = $(content).parent().find('.mod_board_column_sort'),\n direction = $(content).data('sort');\n if (!direction) {\n if (sortby == SORTBY_RATING) {\n direction = 'desc';\n } else {\n direction = 'asc';\n }\n }\n if (toggle) {\n direction = direction == 'asc' ? 'desc' : 'asc';\n }\n\n if (direction == 'asc') {\n sortCol.removeClass('fa-angle-down');\n sortCol.addClass('fa-angle-up');\n } else {\n sortCol.removeClass('fa-angle-up');\n sortCol.addClass('fa-angle-down');\n }\n $(content).data('sort', direction);\n\n var desc,\n asc;\n if (sortby == SORTBY_DATE) {\n desc = function(a, b) {\n return $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_RATING) {\n desc = function(a, b) {\n return $(b).find('.mod_board_rating').text() - $(a).find('.mod_board_rating').text() ||\n $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).find('.mod_board_rating').text() - $(b).find('.mod_board_rating').text() ||\n $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_NONE) {\n let sortElements = (a, b) => {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n $('> .board_note', $(content)).sort(sortElements).appendTo($(content));\n return;\n }\n\n $('> .board_note', $(content)).sort(direction === 'asc' ? asc : desc).appendTo($(content));\n\n };\n\n /**\n * Update sorting of sortable content.\n *\n * @method updateSortable\n */\n var updateSortable = function() {\n let fromColumnID;\n $(\".board_column[data-locked='false'] .board_column_content\").sortable({\n connectWith: \".board_column[data-locked='false'] .board_column_content\",\n cancel: \".mod_board_nosort\",\n handle: \".move_note\",\n start: function(_, ui) {\n fromColumnID = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n var note = $(ui.item),\n tocolumn = note.closest('.board_column'),\n elem = $(this),\n noteid = note.data('ident'),\n columnid = tocolumn.data('ident');\n let columnElements = tocolumn.find('.board_column_content').children();\n let sortorder = columnElements.index($(`.board_note[data-ident=${noteid}]`));\n let payload = {\n id: noteid,\n columnid: columnid,\n ownerid: ownerId,\n sortorder: sortorder\n };\n moveNote(fromColumnID, payload, elem);\n }\n });\n };\n\n /**\n * Move a note to a new position / column.\n *\n * @param {Int} fromColumnID The column the note is being moved from.\n * @param {Object} payload The payload to send to the server.\n * @param {Domnode} elem The element clicked to trigger the move.\n */\n const moveNote = (fromColumnID, payload, elem) => {\n updateSortOrders(fromColumnID, payload.columnid, payload.id, payload.sortorder);\n\n serviceCall('move_note', payload, (result) => {\n if (result.status) {\n lastHistoryId = result.historyid;\n updateNoteAria(payload.id);\n updateBoard();\n sortNotes($(`.board_column[data-ident=${payload.columnid}] .board_column_content`));\n } else {\n if (elem) {\n elem.sortable('cancel');\n }\n }\n });\n };\n\n /**\n * Enable column sorting\n */\n const columnSorting = () => {\n let movingColumnId;\n $(\".mod_board\").sortable({\n connectWith: \".mod_board\",\n axis: \"x\",\n containment: \".mod_board_wrapper\",\n cancel: \".mod_board_nosort\",\n handle: \".mod_column_move\",\n start: function(_, ui) {\n movingColumnId = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n let column = $(ui.item);\n let columns = $(\".mod_board\").find('.board_column');\n let sortorder = columns.index(column);\n let payload = {\n id: movingColumnId,\n sortorder: sortorder\n };\n moveColumn(payload);\n }\n });\n };\n\n /**\n * Move a column to a new position.\n *\n * @param {Object} payload The payload to send to the server.\n */\n const moveColumn = (payload) => {\n serviceCall('move_column', payload, false);\n };\n\n /**\n * Updates the inline data attributes necessary for rendering the lists\n * in the correct sort order. Note: the data attribute values updated by\n * jQuery are not reflected in DOM inspection but are still set.\n * @param {number} fromColumnID The column ID of the column to sort.\n * @param {number} toColumnID The column ID of the column to sort.\n * @param {number} noteID The note ID that was moved.\n * @param {number} newSortOrder The new position of the note sort order.\n */\n const updateSortOrders = (fromColumnID, toColumnID, noteID, newSortOrder) => {\n let toColumn = $(`.board_column[data-ident=${toColumnID}] .board_column_content`);\n let movedNote = $(`.board_note[data-ident=${noteID}]`);\n let oldSortOrder = movedNote.data('sortorder');\n // Check whether it is the same column and then increment or decrement notes above or below\n // then set sortorder according to whether the sortorder has moved up or down.\n let toChildren = toColumn.children();\n if (fromColumnID == toColumnID) {\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (oldSortOrder < newSortOrder) {\n if (sortOrder <= newSortOrder && sortOrder >= oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n } else if (oldSortOrder > newSortOrder) {\n if (sortOrder >= newSortOrder && sortOrder <= oldSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n }\n });\n } else {\n let fromColumn = $(`.board_column[data-ident=${fromColumnID}] .board_column_content`);\n let fromChildren = fromColumn.children();\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder >= newSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n });\n fromChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder > oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n });\n }\n movedNote.data('sortorder', newSortOrder);\n };\n\n /**\n * Get the body fragment for the modal form.\n *\n * @param {number} noteid\n * @param {number} columnid\n * @param {number} ownerId\n * @returns {Deferred|*}\n */\n var getBody = function(noteid, columnid, ownerId) {\n // Get the content of the modal.\n var params = {noteid: noteid, columnid: columnid, ownerid: ownerId};\n return Fragment.loadFragment('mod_board', 'note_form', contextid, params);\n };\n\n /**\n * Setup the aria labels for the modal.\n *\n * @param {object} note\n * @param {object} modal\n */\n var updateModalAria = function(note, modal) {\n let columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text(),\n addYoutube,\n addImage,\n addLink,\n postButton,\n cancelButton,\n modalRoot = modal.getRoot();\n\n if (note.data('ident')) {\n // Is a note update.\n var noteIdentifier = textIdentifierForNote(note);\n\n postButton = strings.aria_postedit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n cancelButton = strings.aria_canceledit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n addYoutube = strings.aria_addmedia.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addImage = strings.aria_addmedia.replace('{type}', strings.option_image).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addLink = strings.aria_addmedia.replace('{type}', strings.option_link).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n } else {\n // Note is new.\n postButton = strings.aria_postnew.replace('{column}', columnIdentifier);\n cancelButton = strings.aria_cancelnew.replace('{column}', columnIdentifier);\n addYoutube = strings.aria_addmedianew.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier);\n addImage = strings.aria_addmedianew.replace('{type}', strings.option_image).replace('{column}', columnIdentifier);\n addLink = strings.aria_addmedianew.replace('{type}', strings.option_link).replace('{column}', columnIdentifier);\n }\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('aria-label', addYoutube);\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('title', addYoutube);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('aria-label', addImage);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('title', addImage);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('aria-label', addLink);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('title', addLink);\n }\n\n let button = modalRoot.find(modal.getActionSelector('save'));\n if (button) {\n button.attr('aria-label', postButton);\n }\n button = modalRoot.find(modal.getActionSelector('cancel'));\n if (button) {\n button.attr('aria-label', cancelButton);\n }\n };\n\n /**\n * Displays the modal form to edit a note.\n *\n * @param {object} note\n */\n var showModalForm = function(note) {\n let noteId = 0,\n columnId = note.data('column'),\n column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n title;\n\n if (note.data('ident')) {\n noteId = note.data('ident');\n title = strings.modal_title_edit.replace('{column}', columnIdentifier);\n } else {\n title = strings.modal_title_new.replace('{column}', columnIdentifier);\n }\n\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: getBody(noteId, columnId, ownerId),\n large: true,\n removeOnClose: true\n }).then(function(modal) {\n // Use the body promise so we know body content is loaded.\n modal.getBodyPromise().then(function () {\n let saveInProgress = false;\n editModal = modal;\n modal.setLarge();\n modal.setSaveButtonText(strings.post_button_text);\n modal.setButtonText('cancel', strings.cancel_button_text);\n\n modal.getRoot().on(ModalEvents.hidden, function () {\n stopNoteEdit();\n if (!note.data('ident')) {\n note.remove();\n }\n });\n\n modal.getRoot().on(ModalEvents.save, function (e) {\n e.preventDefault();\n modal.getRoot().find('form').submit();\n });\n\n var changeEvent = document.createEvent('HTMLEvents');\n changeEvent.initEvent('change', true, true);\n\n modal.getRoot().on('submit', 'form', function (e) {\n e.preventDefault();\n\n // Prevent multiple form submissions from being sent.\n if (saveInProgress) {\n return;\n }\n saveInProgress = true;\n\n // First, make sure the native html5 validity checks are run.\n let valid = modal.getRoot().find('form').get(0).reportValidity();\n if (!valid) {\n saveInProgress = false;\n return;\n }\n\n // Prompt all inputs to run their validation functions.\n // Normally this would happen when the form is submitted, but\n // since we aren't submitting the form normally we need to run client side\n // validation.\n modal.getRoot().find(':input').each(function (index, element) {\n element.dispatchEvent(changeEvent);\n });\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n var invalid = $.merge(\n modal.getRoot().find('[aria-invalid=\"true\"]'),\n modal.getRoot().find('.error'),\n modal.getRoot().find(':invalid')\n );\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n saveInProgress = false;\n return;\n }\n\n var formData = JSON.stringify(modal.getRoot().find('form').serialize());\n serviceCall('submit_form', {contextid: contextid, jsonformdata: formData}, function (result) {\n if (result.status) {\n if (result.action == 'insert') {\n // Added a new note.\n lastHistoryId = result.historyid;\n note.remove();\n addNote(columnId, result.note.id, result.note.heading, result.note.content,\n {type: result.note.type, info: result.note.info, url: result.note.url},\n {id: result.note.userid}, result.note.timecreated, result.note.rating);\n sortNotes($('.board_column[data-ident=' + columnId + '] .board_column_content'));\n updateNoteAria(result.note.id);\n } else {\n // Updated existing note.\n lastHistoryId = result.historyid;\n getNoteTextForNote(note).html(result.note.content);\n getNoteHeadingForNote(note).html(result.note.heading);\n updateNoteAria(result.note.id);\n setAttachment(note, {\n type: result.note.type,\n info: result.note.info, url: result.note.url\n });\n }\n stopNoteEdit();\n\n // Clear the form changed checker.\n Y.use('moodle-core-formchangechecker', function() {\n M.core_formchangechecker.reset_form_dirty_state();\n });\n\n modal.destroy();\n } else {\n modal.destroy();\n }\n });\n\n });\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n // First hide the select menu.\n modal.getRoot().find('#fitem_id_mediatype').hide();\n\n let mediaSelect = modal.getRoot().find('#fitem_id_mediatype select'),\n ytButton = modal.getRoot().find('.mod_board_attachment_button.youtube_button'),\n pictureButton = modal.getRoot().find('.mod_board_attachment_button.image_button'),\n linkButton = modal.getRoot().find('.mod_board_attachment_button.link_button'),\n updateMediaButtons = function() {\n ytButton.removeClass('selected');\n pictureButton.removeClass('selected');\n linkButton.removeClass('selected');\n switch (mediaSelect.val()) {\n case (\"1\"):\n ytButton.addClass('selected');\n break;\n case (\"2\"):\n pictureButton.addClass('selected');\n break;\n case (\"3\"):\n linkButton.addClass('selected');\n break;\n }\n };\n\n updateMediaButtons();\n handleAction(ytButton, function() {\n if (mediaSelect.val() === \"1\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(1);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(pictureButton, function() {\n if (mediaSelect.val() === \"2\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(2);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(linkButton, function() {\n if (mediaSelect.val() === \"3\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(3);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n } else {\n modal.getRoot().find('#fitem_id_mediabuttons').hide();\n }\n\n updateModalAria(note, modal);\n modal.show();\n\n return modal;\n }).catch(Notification.exception);\n return modal;\n }).catch(Notification.exception);\n };\n\n /**\n * Show the note in a modal\n * @param {Int} ident The note id\n * @param {Object} notecontent The note content\n */\n var fullScreenNote = (ident, notecontent) => {\n const heading = getNoteHeadingForNote(notecontent).html();\n const modalBody = $(document.createElement('div'));\n modalBody.addClass('mod_board_note_content');\n const text = getNoteTextForNote(notecontent);\n if (text) {\n modalBody.append(text.clone());\n }\n const preview = getNotePreviewForNote(notecontent);\n if (preview) {\n modalBody.append(preview.clone());\n }\n\n // Adds the comments to a note.\n const commentArea = $(document.createElement('div'));\n commentArea.attr('data-region', 'comment-area');\n modalBody.append(commentArea);\n Comments.fetchFor(ident, commentArea);\n\n ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: heading,\n body: modalBody,\n }).then(function(modal) {\n modal.setLarge();\n modal.show();\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function () {\n // Destroy when hidden.\n modal.destroy();\n });\n return modal;\n }, this).catch(Notification.exception);\n };\n\n /**\n * Initialize board.\n *\n * @method init\n */\n var init = function() {\n serviceCall('get_board', {id: board.id, ownerid: ownerId}, function(columns) {\n // Init\n if (columns) {\n for (var index in columns) {\n addColumn(\n columns[index].id,\n columns[index].name,\n columns[index].locked,\n columns[index].notes || {},\n options.colours[columns[index].id % options.colours.length]\n );\n }\n }\n\n if (isEditor) {\n addNewColumnButton();\n }\n\n lastHistoryId = board.historyid;\n\n if (isEditor) {\n updateSortable();\n columnSorting();\n }\n\n updateBoard();\n });\n };\n\n // Get strings\n var stringsInfo = [];\n for (var string in strings) {\n stringsInfo.push({key: string, component: 'mod_board'});\n }\n\n $.when(getStrings(stringsInfo)).done(function(results) {\n var index = 0;\n for (string in strings) {\n strings[string] = results[index++];\n }\n\n init();\n });\n}\n"],"names":["settings","strings","default_column_heading","post_button_text","cancel_button_text","remove_note_title","remove_note_text","remove_column_title","note_changed_title","note_changed_text","note_deleted_text","rate_note_title","rate_note_text","rate_remove_note_text","Ok","delete","Cancel","warning","modal_title_new","modal_title_edit","option_youtube","option_image","option_link","aria_newcolumn","aria_newpost","aria_deletecolumn","aria_movecolumn","aria_deletepost","aria_movepost","aria_editpost","aria_addmedia","aria_addmedianew","aria_deleteattachment","aria_postedit","aria_canceledit","aria_postnew","aria_cancelnew","aria_ratepost","invalid_file_extension","invalid_file_size_min","invalid_file_size_max","invalid_youtube_url","options","JSON","parse","board","contextid","reloadTimer","lastHistoryId","isEditor","usersCanEdit","userId","parseInt","ownerId","mediaSelection","mediaselection","editingNote","isReadOnlyBoard","readonly","ratingenabled","sortby","editModal","enableblanktarget","serviceCall","method","args","callback","failcallback","stopUpdating","call","methodname","done","data","fail","error","exception","_serviceCall","apply","arguments","updateBoard","getNote","ident","getNoteTextForNote","note","find","getNoteHeadingForNote","getNoteBorderForNote","getNoteAttachmentsForNote","textIdentifierForNote","noteText","html","noteHeading","noteAttachment","attachmentDataForNote","length","replace","split","slice","join","info","updateNoteAria","noteId","columnIdentifier","closest","text","noteIdentifier","deleteNoteString","attr","moveNoteString","editNoteString","updateColumnAria","columnId","column","newNoteString","moveColumnString","deleteColumnString","each","index","stopNoteEdit","noteBorder","show","hide","remove","sortAfterDelete","columnID","sortorder","getColumn","children","filter","_","element","so","setAttachment","attachment","type","attType","val","decodeText","url","attachmentInfo","attachmentUrl","attachmentFile","prop","attachmentTypeToString","FileReader","attachmentTypeChanged","previewAttachment","filename","filecontents","encodeText","fileElem","elem","removeClass","addClass","blanktarget","videoID","match","undefined","getEmbedUrl","addNote","columnid","heading","content","owner","rating","ismynote","id","iseditable","pendingNote","notecontent","notecontrols","noteAriaText","attachmentPreview","append","columnContent","beginEdit","showModalForm","startNoteEdit","rateElement","handleAction","result","canrate","rateRemoveText","hasrated","confirm","status","historyid","sortNotes","then","rateModal","getRoot","on","ModalEvents","hidden","rateNote","removeElement","deleteNote","moveElement","init","moveNote","editElement","updateSortable","fullScreenNote","lastOne","last","insertAfter","prepend","addColumn","name","locked","notes","colour","headerStyle","nameCache","columnHeader","columnSort","columnName","columnNewContent","hideheaders","lockIcon","lockElement","lockstring","str","lockColumn","moveColumn","getColumnName","callBeforeOnKeyEditing","is","Error","e","isAriaTriggerKey","keyCode","preventDefault","editable","handleEditableAction","toggleFontSize","closeOnEnter","newNoteButton","noteicon","timecreated","userid","columnSorting","selectHeadingColour","colCount","colourCount","colours","updateNote","processBoardHistory","ownerid","since","boardhistory","item","boardid","action","formModal","historyData","alert","forEach","detach","appendTo","instant","history_refresh","setTimeout","clearTimeout","toggle","desc","asc","sortCol","parent","direction","a","b","sortElements","sort","fromColumnID","sortable","connectWith","cancel","handle","start","ui","stop","tocolumn","this","noteid","payload","updateSortOrders","movingColumnId","axis","containment","toColumnID","noteID","newSortOrder","toColumn","movedNote","oldSortOrder","toChildren","sortOrder","fromChildren","getBody","params","Fragment","loadFragment","title","create","ModalFactory","types","SAVE_CANCEL","body","large","removeOnClose","modal","getBodyPromise","saveInProgress","setLarge","setSaveButtonText","setButtonText","save","submit","changeEvent","document","createEvent","initEvent","get","reportValidity","dispatchEvent","invalid","$","merge","first","focus","formData","stringify","serialize","jsonformdata","Y","use","M","core_formchangechecker","reset_form_dirty_state","destroy","mediaSelect","ytButton","pictureButton","linkButton","updateMediaButtons","addYoutube","addImage","addLink","postButton","cancelButton","modalRoot","button","getActionSelector","updateModalAria","catch","Notification","modalBody","createElement","clone","preview","commentArea","fetchFor","CANCEL","columns","newBusy","columnicon","stringsInfo","string","push","key","component","when","results","rawText","encodedText"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"board.min.js","sources":["../src/board.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle the board.\n *\n * @author Karen Holland \n * @copyrigt 2021 Brickfield Education Labs \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from \"jquery\";\nimport {get_strings as getStrings, get_string as getString} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport ModalFactory from \"core/modal_factory\";\nimport ModalEvents from \"core/modal_events\";\nimport Notification from \"core/notification\";\nimport \"mod_board/jquery.editable.amd\";\nimport \"mod_board/jquery.sortable.amd\";\nimport Fragment from \"core/fragment\";\nimport Comments from \"mod_board/comments\";\nimport moveNotesDialog from \"./movenotesdialog\";\nimport moveColumnsDialog from \"./movecolumnsdialog\";\n\n/**\n * Execute a ajax call to a mod_board ajax service.\n *\n * @param {string} method\n * @param {array} args\n * @param {method} callback\n * @param {method} failcallback\n * @private\n */\nconst _serviceCall = function(method, args, callback, failcallback) {\n Ajax.call([{\n methodname: 'mod_board_' + method,\n args: args,\n done: function(data) {\n callback(data);\n },\n fail: function(error) {\n Notification.exception(error);\n if (failcallback) {\n failcallback(error);\n }\n }\n }]);\n};\n\n/**\n * Indicates if this is a keycode we want to listend to for\n * aria purposes.\n *\n * @returns {boolean}\n * @param {number} key\n */\nconst isAriaTriggerKey = function(key) {\n return key == 13 || key == 32;\n};\n\n/**\n * Encodes text into html entities.\n *\n * @param {string} rawText\n * @returns {*|jQuery}\n */\nconst encodeText = function(rawText) {\n return $('
').text(rawText).html();\n};\n\n/**\n * Decodes text from html entities.\n *\n * @param {string} encodedText\n * @returns {*|jQuery}\n */\nconst decodeText = function(encodedText) {\n return $('
').html(encodedText).text();\n};\n\n/**\n * Handler for keypress and click actions.\n *\n * @param {object} elem\n * @param {function} callback\n * @returns {*}\n */\nconst handleAction = function(elem, callback) {\n return elem.on('click keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode)) {\n e.preventDefault();\n } else {\n return;\n }\n }\n\n callback();\n e.preventDefault();\n });\n};\n\n/**\n * Setting up element edibility.\n *\n * @param {object} elem\n * @param {function} callback\n * @param {function} callBeforeOnKeyEditing\n * @returns {*}\n */\nconst handleEditableAction = function(elem, callback, callBeforeOnKeyEditing) {\n if (elem.is(':editable')) {\n throw new Error('handleEditableAction - must be called before setting the element as editable');\n }\n\n // Can't use on(edit) here because we want to do actions (save cache) before the control goes into edit mode\n return elem.on('dblclick keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode) && !elem.is(':editing')) {\n e.preventDefault();\n if (callBeforeOnKeyEditing) {\n callback();\n }\n elem.editable('open');\n if (callBeforeOnKeyEditing) {\n return;\n }\n } else {\n return;\n }\n }\n\n callback();\n });\n};\n\n/**\n * The default function of the module, which does the setup of the page.\n *\n * @param {object} settings\n */\nexport default function(settings) {\n // An array of strings to load as a batch later.\n // Not necessary, but used to load all the strings in one ajax call.\n var strings = {\n default_column_heading: '',\n post_button_text: '',\n cancel_button_text: '',\n remove_note_title: '',\n remove_note_text: '',\n remove_column_title: '',\n note_changed_title: '',\n note_changed_text: '',\n note_deleted_text: '',\n rate_note_title: '',\n rate_note_text: '',\n rate_remove_note_text: '',\n Ok: '',\n delete: '',\n Cancel: '',\n warning: '',\n modal_title_new: '',\n modal_title_edit: '',\n option_youtube: '',\n option_image: '',\n option_link: '',\n\n aria_newcolumn: '',\n aria_newpost: '',\n aria_deletecolumn: '',\n aria_movecolumn: '',\n aria_deletepost: '',\n aria_movepost: '',\n aria_editpost: '',\n aria_addmedia: '',\n aria_addmedianew: '',\n aria_deleteattachment: '',\n aria_postedit: '',\n aria_canceledit: '',\n aria_postnew: '',\n aria_cancelnew: '',\n aria_ratepost: '',\n\n invalid_file_extension: '',\n invalid_file_size_min: '',\n invalid_file_size_max: '',\n\n invalid_youtube_url: '',\n };\n\n // Json decode the strings from the settings.\n var options = JSON.parse(settings.settings) || {};\n var board = options.board || {};\n var contextid = options.contextid;\n\n const MEDIA_SELECTION_BUTTONS = 1,\n ATTACHMENT_VIDEO = 1,\n ATTACHMENT_IMAGE = 2,\n ATTACHMENT_LINK = 3,\n SORTBY_DATE = 1,\n SORTBY_RATING = 2,\n SORTBY_NONE = 3;\n\n var reloadTimer = null,\n lastHistoryId = null,\n isEditor = options.isEditor || false,\n usersCanEdit = options.usersCanEdit,\n userId = parseInt(options.userId) || -1,\n userFirstname = options.firstname,\n userLastname = options.lastname,\n ownerId = parseInt(options.ownerId),\n mediaSelection = options.mediaselection || MEDIA_SELECTION_BUTTONS,\n editingNote = 0,\n isReadOnlyBoard = options.readonly || false,\n showauthorofnote = options.showauthorofnote || false,\n ratingenabled = options.ratingenabled,\n sortby = options.sortby || SORTBY_DATE,\n editModal = null,\n enableblanktarget = (parseInt(options.enableblanktarget) === 1);\n\n /**\n * Helper method to make calls to mod_board external services.\n *\n * @param {string} method\n * @param {array} args\n * @param {function} callback\n * @param {function} failcallback\n */\n var serviceCall = function(method, args, callback, failcallback) {\n if (method !== 'board_history') {\n stopUpdating();\n }\n _serviceCall(method, args, function() {\n if (callback) {\n callback.apply(null, arguments);\n }\n if (method !== 'board_history' && method != 'get_board') {\n updateBoard(true);\n }\n }, failcallback);\n };\n\n /**\n * Returns the jquery element of a given note identifier.\n *\n * @param {number} ident\n * @returns {jQuery}\n */\n var getNote = function(ident) {\n return $(\".board_note[data-ident='\" + ident + \"']\");\n };\n\n /**\n * Returns the jquery element of the note text for the given note element.\n *\n * @method getNoteTextForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteTextForNote = function(note) {\n return $(note).find(\".mod_board_note_text\");\n };\n\n /**\n * Returns the jquery element of the preview for the given note element.\n *\n * @method getNotePreviewForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNotePreviewForNote = (note) => {\n return $(note).find(\".mod_board_preview\");\n };\n\n\n /**\n * Returns the jquery element of the note heading for the given note element.\n *\n * @method getNoteHeadingForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteHeadingForNote = function(note) {\n return $(note).find(\".mod_board_note_heading\");\n };\n\n /**\n * Returns the jquery element of the note border for the given note element.\n *\n * @method getNoteBorderForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteBorderForNote = function(note) {\n return $(note).find(\".mod_board_note_border\");\n };\n\n /**\n * Gets a jquery node for the attachments of a given note.\n *\n * @method getNoteAttachmentsForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteAttachmentsForNote = function(note) {\n return $(note).find(\".mod_board_note_attachment\");\n };\n\n /**\n * Creates text identifier for a given node.\n *\n * @method textIdentifierForNote\n * @param {object} note\n * @returns {null|*|jQuery}\n */\n var textIdentifierForNote = function(note) {\n var noteText = getNoteTextForNote(note).html(),\n noteHeading = getNoteHeadingForNote(note).html(),\n noteAttachment = attachmentDataForNote(note);\n\n if (noteHeading.length > 0) {\n return noteHeading;\n }\n if (noteText.length > 0) {\n return noteText.replace(//gi, \" \").replace(/\\n/g, \" \").split(/\\s+/).slice(0, 5).join(\" \");\n }\n if (noteAttachment.info && noteAttachment.info.length > 0) {\n return noteAttachment.info;\n }\n return null;\n };\n\n /**\n * Update the Aria info for a given note id.\n *\n * @method updateNoteAria\n * @param {number} noteId\n */\n var updateNoteAria = function(noteId) {\n var note = getNote(noteId),\n columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text();\n\n if (noteId) { // New post\n var noteIdentifier = textIdentifierForNote(note),\n deleteNoteString = strings.aria_deletepost.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n\n note.find('.delete_note').attr('aria-label', deleteNoteString).attr('title', deleteNoteString);\n\n var moveNoteString = strings.aria_movepost.replace('{post}', noteIdentifier);\n note.find('.move_note').attr('aria-label', moveNoteString).attr('title', moveNoteString);\n\n var editNoteString = strings.aria_editpost.replace('{post}', noteIdentifier);\n note.find('.edit_note').attr('aria-label', editNoteString).attr('title', editNoteString);\n\n note.find('.mod_board_rating').attr('aria-label', strings.aria_ratepost.replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier));\n note.find('.note_ariatext').html(noteIdentifier);\n }\n\n };\n\n /**\n * Update the Aria information for a given column id.\n *\n * @method updateColumnAria\n * @param {number} columnId\n */\n var updateColumnAria = function(columnId) {\n var column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n newNoteString = strings.aria_newpost.replace('{column}', columnIdentifier),\n moveColumnString = strings.aria_movecolumn.replace('{column}', columnIdentifier),\n deleteColumnString = strings.aria_deletecolumn.replace('{column}', columnIdentifier);\n column.find('.newnote').attr('aria-label', newNoteString).attr('title', newNoteString);\n column.find('.mod_column_move').attr('aria-label', moveColumnString).attr('title', moveColumnString);\n column.find('.delete_column').attr('aria-label', deleteColumnString).attr('title', deleteColumnString);\n\n column.find(\".board_note\").each(function(index, note) {\n updateNoteAria($(note).data('ident'));\n });\n };\n\n /**\n * Stop the current note editing process.\n *\n * @method stopNoteEdit\n */\n var stopNoteEdit = function() {\n if (!editingNote) {\n getNote(0).remove();\n return;\n }\n\n var note = getNote(editingNote);\n\n if (note) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n }\n\n editingNote = 0;\n };\n\n /**\n * Start the editing of a particular note, by identifier.\n *\n * @method startNoteEdit\n * @param {number} ident\n */\n var startNoteEdit = function(ident) {\n\n if (editingNote) {\n if (editingNote == ident) {\n return;\n }\n stopNoteEdit();\n }\n\n if (ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n var note = getNote(ident);\n if (note) {\n showModalForm(note);\n\n if (ident) {\n editingNote = ident;\n }\n }\n };\n\n /**\n * Delete a given note, by identifier.\n *\n * @method deleteNote\n * @param {number} ident\n */\n var deleteNote = function(ident) {\n Notification.confirm(\n strings.remove_note_title, // Are you sure?\n strings.remove_note_text, // This will effect others.\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_note', { id: ident }, function (result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n let note = getNote(ident);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n }\n });\n }\n );\n };\n\n /**\n * This function gets a board column as a jQuery element.\n * @param {number} columnID The column ID.\n * @returns {jQuery}\n */\n const getColumn = (columnID) => {\n return $(`.board_column[data-ident='${columnID}'] .board_column_content`);\n };\n\n const sortAfterDelete = (columnID, sortorder) => {\n let column = getColumn(columnID);\n let elements = column.children().filter((_, element) => {\n return parseInt($(element).data('sortorder')) > parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so - 1);\n });\n };\n\n /**\n * Rate (star) a give note, by identifier.\n *\n * @method rateNote\n * @param {number} ident\n */\n var rateNote = function(ident) {\n if (!ratingenabled) {\n return;\n }\n if (isReadOnlyBoard) {\n return;\n }\n\n var note = getNote(ident),\n rating = note.find('.mod_board_rating');\n if (rating.data('disabled')) {\n return;\n }\n rating.data('disabled', true);\n\n serviceCall('can_rate_note', {id: ident}, function(result) {\n if (result.canrate) {\n const rateRemoveText = result.hasrated ? strings.rate_remove_note_text : strings.rate_note_text;\n Notification.confirm(\n strings.rate_note_title,\n rateRemoveText, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n serviceCall('rate_note', {id: ident}, function(result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n rating.html(` ${result.rating} `);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n rating.data('disabled', false);\n });\n }\n ).then(function(rateModal) {\n // Do this here, because it catches both cancel clicks, or someone clicking the X.\n rateModal.getRoot().on(ModalEvents.hidden, function() {\n rating.data('disabled', false);\n });\n });\n }\n });\n };\n\n /**\n * Update the attachment information of a note.\n *\n * @method attachmentTypeChanged\n * @param {object} note\n */\n var attachmentTypeChanged = function(note) {\n var noteAttachment = getNoteAttachmentsForNote(note),\n type = noteAttachment.find('.mod_board_type').val(),\n attachmentInfo = noteAttachment.find('.info'),\n attachmentUrl = noteAttachment.find('.url'),\n attachmentFile = noteAttachment.find('.mod_board_file');\n\n if (type > \"0\") {\n attachmentInfo.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_info']);\n attachmentUrl.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_url']);\n\n attachmentInfo.show();\n if (type == ATTACHMENT_IMAGE && FileReader) {\n attachmentFile.show();\n attachmentUrl.hide();\n } else {\n attachmentFile.hide();\n attachmentUrl.show();\n }\n } else {\n attachmentInfo.hide();\n attachmentUrl.hide();\n attachmentFile.hide();\n\n attachmentInfo.val('');\n attachmentUrl.val('');\n\n }\n };\n\n /**\n * Set the attachment of a note.\n *\n * @method setAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var setAttachment = function(note, attachment) {\n var noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment) {\n if (!attachment) {\n attachment = {type: \"0\"};\n } else {\n attachment.type += \"\";// Just in case\n }\n var attType = noteAttachment.find('.mod_board_type');\n attType.val(attachment.type ? attachment.type : \"0\");\n if (attType.val() > \"0\") {\n noteAttachment.find('.info').val(decodeText(attachment.info));\n noteAttachment.find('.url').val(decodeText(attachment.url));\n }\n attachmentTypeChanged(note, attachment);\n }\n previewAttachment(note, attachment);\n };\n\n /**\n * Returns an object with various information about a note's attachment.\n *\n * @method attachmentDataForNote\n * @param {object} note\n * @returns {{filename: null, filecontents: null, type: number, url: null, info: null}}\n */\n var attachmentDataForNote = function(note) {\n var attachment = {type: 0, info: null, url: null, filename: null, filecontents: null},\n noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment.length) {\n attachment.type = noteAttachment.find('.mod_board_type').val();\n attachment.info = encodeText(noteAttachment.find('.info').val());\n attachment.url = encodeText(noteAttachment.find('.url').val());\n var fileElem = noteAttachment.find('.mod_board_file>input');\n if (fileElem.data('filename')) {\n attachment.filename = fileElem.data('filename');\n attachment.filecontents = fileElem.data('filecontents');\n }\n }\n if ((!attachment.info || !attachment.info.length) && (!attachment.url || !attachment.url.length) &&\n (!attachment.filename)) {\n attachment.type = 0;\n }\n\n return attachment;\n };\n\n /**\n * Get the string type of a attachment type number.\n *\n * @method attachmentTypeToString\n * @param {number} type\n * @returns {string|null}\n */\n var attachmentTypeToString = function(type) {\n switch (type) {\n case \"1\": return 'youtube';\n case \"2\": return 'image';\n case \"3\": return 'link';\n default: return null;\n }\n };\n\n /**\n * This parses a youtube video ID from a URL. We can use this ID to\n * construct the embed URL.\n * @param {string} url The URL entered to the modal.\n * @returns {string | null} The youtube embed URL or null.\n */\n const getEmbedUrl = (url) => {\n // Thanks for the regex from: https://gist.github.com/rodrigoborgesdeoliveira/987683cfbfcc8d800192da1e73adc486.\n let regex = /(\\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/;\n let videoID = url.match(regex);\n if (!videoID || videoID[2] === undefined || videoID[2].length !== 11) {\n return null;\n }\n return `https://www.youtube-nocookie.com/embed/${videoID[2]}`;\n };\n\n /**\n * Display the attachment preview for a note.\n *\n * @method previewAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var previewAttachment = function(note, attachment) {\n var elem = note.find('.mod_board_preview');\n if (!attachment) {\n attachment = attachmentDataForNote(note);\n }\n\n if (!getNoteTextForNote(note).html().length) {\n elem.addClass('mod_board_notext');\n } else {\n elem.removeClass('mod_board_notext');\n }\n\n elem.removeClass('wrapper_youtube');\n elem.removeClass('wrapper_image');\n elem.removeClass('wrapper_url');\n if (attachment.filename && parseInt(attachment.type) == ATTACHMENT_IMAGE) { // Before uploading\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n } else if (attachment.url) {\n const blanktarget = enableblanktarget ? ' target=\"_blank\"' : '';\n switch (parseInt(attachment.type)) {\n case ATTACHMENT_VIDEO: { // Youtube\n let url = getEmbedUrl(attachment.url);\n if (url === null) {\n elem.html(strings.invalid_youtube_url);\n } else {\n elem.html('');\n elem.addClass('wrapper_youtube').addClass('position-relative');\n }\n elem.show();\n }\n break;\n case ATTACHMENT_IMAGE: // Image\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n break;\n case ATTACHMENT_LINK: // Url\n elem.html('' +\n (attachment.info || attachment.url) + '');\n elem.addClass('wrapper_url');\n elem.show();\n break;\n default:\n elem.html('');\n elem.hide();\n }\n } else {\n elem.html('');\n elem.hide();\n }\n };\n\n /**\n * Add a new note with the given information.\n *\n * @method addNote\n * @param {number} columnid\n * @param {number} ident\n * @param {string} heading\n * @param {string} content\n * @param {object} attachment\n * @param {object} owner\n * @param {number} sortorder\n * @param {string} rating\n */\n var addNote = function(columnid, ident, heading, content, attachment, owner, sortorder, rating) {\n var ismynote = owner.id == userId || !ident;\n var iseditable = isEditor || (ismynote && !isReadOnlyBoard);\n\n if (!ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n // Making space for this note if necessary in the sort order.\n if (sortby == SORTBY_NONE) {\n let children = $(`.board_column[data-ident='${columnid}'] .board_column_content`).children();\n let elements = children.filter((_, element) => {\n return parseInt($(element).data('sortorder')) >= parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so + 1);\n });\n }\n\n var note = $('
');\n if (ismynote) {\n note.addClass('mod_board_mynote');\n }\n if (iseditable) {\n note.addClass('mod_board_editablenote');\n }\n if (!ismynote && !iseditable) {\n note.addClass('mod_board_nosort');\n }\n\n var notecontent = $('
'),\n notecontrols = $('
'),\n noteHeading = $('
' + (heading ? heading : '') + '
'),\n noteAuthorusername = $(''),\n noteBorder = $('
'),\n noteText = $('
' + (content ? content : '') + '
'),\n noteAriaText = $('
'),\n attachmentPreview = $('
');\n\n if (showauthorofnote) {\n let firstname = '';\n let lastname = '';\n if (ismynote) {\n // Use the Name of the user itself. We do not need to get this information from somewhere else.\n firstname = userFirstname;\n lastname = userLastname;\n } else {\n firstname = owner.firstname;\n lastname = owner.lastname;\n }\n\n noteAuthorusername = '
' +\n ' ' +\n '' +\n firstname +\n '' +\n '' +\n lastname +\n '' +\n '
' ;\n }\n\n notecontent.append(noteHeading);\n notecontent.append(noteAuthorusername);\n notecontent.append(noteBorder);\n notecontent.append(noteText);\n notecontent.append(noteAriaText);\n\n notecontent.append(attachmentPreview);\n note.append(notecontent);\n\n var columnContent = $('.board_column[data-ident=' + columnid + '] .board_column_content');\n\n var beginEdit = () => {\n startNoteEdit(ident);\n };\n\n if (ident) {\n if (ratingenabled) {\n note.addClass('mod_board_rateablenote');\n var rateElement = $(`
${rating}
`);\n\n handleAction(rateElement, () => {\n rateNote(ident);\n });\n notecontrols.append(rateElement);\n }\n\n if (iseditable) {\n var removeElement = $('
');\n handleAction(removeElement, () => {\n deleteNote(ident);\n });\n\n notecontrols.append(removeElement);\n\n if (usersCanEdit == 1 || isEditor) {\n var moveElement = $('
');\n notecontrols.append(moveElement);\n moveNotesDialog.init(ownerId, moveNote);\n }\n\n var editElement = $('
');\n notecontrols.append(editElement);\n handleAction(editElement, () => {\n beginEdit();\n });\n updateSortable();\n setAttachment(note, attachment);\n } else {\n previewAttachment(note, attachment);\n }\n\n note.append(notecontrols);\n\n handleAction(notecontent, () => fullScreenNote(ident, notecontent));\n\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n\n var lastOne = columnContent.find(\".board_note\").last();\n\n if (lastOne.length) {\n note.insertAfter(lastOne);\n } else {\n columnContent.prepend(note);\n }\n } else {\n $('.board_column[data-ident=' + columnid + '] .board_column_newcontent').append(note);\n // This is effectively a note placeholder. So we don't need to show it.\n note.hide();\n beginEdit();\n }\n };\n\n /**\n * Add a new column.\n *\n * @method addColumn\n * @param {object} ident\n * @param {string} name\n * @param {bool} locked\n * @param {array} notes\n * @param {string} colour\n */\n var addColumn = function(ident, name, locked, notes, colour) {\n let headerStyle = `style=\"border-top: 10px solid #${colour}\"`;\n var iseditable = isEditor,\n nameCache = null,\n column = $(`
`),\n columnHeader = $('
'),\n columnSort = $('
'),\n columnName = $('
' + name + '
'),\n columnContent = $('
'),\n columnNewContent = $('
');\n // Only add the sort button if it makes sense.\n if (sortby != SORTBY_NONE) {\n columnHeader.append(columnSort);\n }\n columnHeader.append(columnName);\n\n if (options.hideheaders) {\n columnName.addClass('d-none');\n }\n\n columnSort.on('click', function() {\n sortNotes(columnContent, true);\n });\n\n if (iseditable) {\n column.addClass('mod_board_editablecolumn');\n const lockIcon = locked ? 'fa-lock' : 'fa-unlock';\n const lockElement = $(`
`);\n const lockstring = locked ? 'aria_column_locked' : 'aria_column_unlocked';\n getString(lockstring, 'mod_board', name).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n\n handleAction(lockElement, () => {\n const lockColumn = column.attr('data-locked') !== 'true';\n serviceCall('lock_column', {id: ident, status: lockColumn}, function(result) {\n const columnName = column.find('.mod_board_column_name').text();\n if (result.status) {\n if (lockColumn) {\n lockElement.removeClass('fa-unlock').addClass('fa-lock');\n column.attr('data-locked', 'true');\n column.find('.board_button.newnote').addClass('d-none');\n getString('aria_column_locked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n } else {\n lockElement.removeClass('fa-lock').addClass('fa-unlock');\n column.attr('data-locked', 'false');\n column.find('.board_button.newnote').removeClass('d-none');\n getString('aria_column_unlocked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n }\n lastHistoryId = result.historyid;\n updateSortable();\n }\n });\n });\n columnHeader.append(lockElement);\n\n columnHeader.addClass('icon-size-3');\n const moveElement = $('
');\n columnHeader.append(moveElement);\n moveColumnsDialog.init(moveColumn);\n var removeElement = $('
');\n handleAction(removeElement, () => {\n Notification.confirm(\n strings.remove_column_title, // Are you sure?\n getString('remove_column_text', 'mod_board', getColumnName(ident)),\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_column', {id: ident}, function(result) {\n if (result.status) {\n column.remove();\n lastHistoryId = result.historyid;\n }\n });\n }\n );\n });\n\n columnHeader.append(removeElement);\n }\n\n column.append(columnHeader);\n column.append(columnContent);\n column.append(columnNewContent);\n\n if (iseditable) {\n handleEditableAction(columnName, function() {\n nameCache = columnName.html();\n }, true);\n\n columnName.editable({\n toggleFontSize: false,\n closeOnEnter: true,\n callback: function(data) {\n if (data.content) {\n serviceCall('update_column', {id: ident, name: columnName.html()}, function(result) {\n if (!result.status) {\n columnName.html(nameCache);\n nameCache = null;\n } else {\n lastHistoryId = result.historyid;\n updateColumnAria(ident);\n }\n }, function() {\n columnName.html(nameCache);\n nameCache = null;\n });\n } else {\n columnName.html(nameCache);\n nameCache = null;\n }\n }\n });\n }\n\n if (!isReadOnlyBoard) {\n const newNoteButton = $('
' +\n '
');\n columnNewContent.append(newNoteButton);\n if (column.attr('data-locked') === 'true') {\n newNoteButton.addClass('d-none');\n }\n handleAction(columnNewContent.find('.newnote'), function() {\n // We do not need to add firstname and lasname because we use ismynote and actual board user.\n addNote(ident, 0, null, null, null, {id: userId}, 0, 0);\n });\n }\n\n var lastOne = $(\".mod_board .board_column_hasdata\").last();\n if (lastOne.length) {\n column.insertAfter(lastOne);\n } else {\n $(\".mod_board\").append(column);\n }\n\n if (notes) {\n for (var index in notes) {\n let sortorder = sortby == 3 ? notes[index].sortorder : notes[index].timecreated;\n\n addNote(ident, notes[index].id, notes[index].heading, notes[index].content,\n {type: notes[index].type, info: notes[index].info, url: notes[index].url},\n {id: notes[index].userid, firstname: notes[index].firstname, lastname: notes[index].lastname},\n sortorder, notes[index].rating);\n }\n }\n sortNotes(columnContent);\n updateColumnAria(ident);\n if (isEditor || usersCanEdit == 1) {\n updateSortable();\n }\n if (isEditor) {\n columnSorting();\n }\n };\n\n /**\n * Gets the text name used in the heading of a column.\n * @param {number} id The ID data attribute on the column element.\n * @returns {string}\n */\n const getColumnName = (id) => {\n return $(`.board_column[data-ident='${id}']`).find('.mod_board_column_name').html();\n };\n\n /**\n * Add the new column button.\n *\n * @method addNewColumnButton\n */\n var addNewColumnButton = function() {\n var column = $('
'),\n newBusy = false;\n column.append('
');\n\n handleAction(column.find('.newcolumn'), function() {\n if (newBusy) {\n return;\n }\n newBusy = true;\n\n serviceCall('add_column', {boardid: board.id, name: strings.default_column_heading}, function(result) {\n addColumn(result.id, strings.default_column_heading, false, {}, selectHeadingColour());\n lastHistoryId = result.historyid;\n newBusy = false;\n }, function() {\n newBusy = false;\n });\n });\n\n $(\".mod_board\").append(column);\n };\n\n /**\n * This selects the next heading colour from options based on the count of the\n * current columns. Length of decremented by one as the new column button is\n * also denoted as a column.\n * @returns {string} colour hex string.\n */\n const selectHeadingColour = () => {\n let colCount = $('.board_column').length - 1;\n let colourCount = options.colours.length;\n return options.colours[colCount % colourCount];\n };\n\n /**\n * Update a note with the provided information.\n *\n * @method updateNote\n * @param {object} note\n * @param {string} heading\n * @param {object} data\n */\n var updateNote = function(note, heading, data) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n noteText.html(data.content);\n noteHeading.html(data.heading);\n setAttachment(note, data.attachment);\n updateNoteAria(data.id);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n };\n\n /**\n * Fetch and process the recent board history.\n *\n * @method processBoardHistory\n */\n var processBoardHistory = function() {\n serviceCall('board_history', {id: board.id, ownerid: ownerId, since: lastHistoryId}, function(boardhistory) {\n for (var index in boardhistory) {\n var item = boardhistory[index];\n if (item.boardid != board.id) {\n continue; // Hmm\n }\n\n var data = JSON.parse(item.content);\n if (item.action == 'add_note') {\n let sortorder = sortby == 3 ? data.sortorder : data.timecreated;\n addNote(data.columnid, data.id, data.heading, data.content, data.attachment,\n {id: item.userid}, sortorder, data.rating);\n updateNoteAria(data.id);\n sortNotes($('.board_column[data-ident=' + data.columnid + '] .board_column_content'));\n } else if (item.action == 'update_note') {\n let note = getNote(data.id),\n formModal = editModal,\n historyData = data;\n if (note) {\n let noteHeading = getNoteHeadingForNote(note);\n\n if (editingNote == data.id) {\n Notification.confirm(\n strings.note_changed_title, // Confirm.\n strings.note_changed_text, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n formModal.hide();\n updateNote(note, noteHeading, historyData);\n stopNoteEdit();\n }\n );\n } else {\n updateNote(note, noteHeading, data);\n }\n }\n } else if (item.action == 'delete_note') {\n if (editingNote == data.id) {\n Notification.alert(strings.warning, strings.note_deleted_text);\n stopNoteEdit();\n }\n let note = getNote(data.id);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n\n } else if (item.action == 'add_column') {\n addColumn(data.id, data.name, false, {}, selectHeadingColour());\n } else if (item.action == 'move_column') {\n const board = $('.mod_board');\n data.sortorder.forEach(column => {\n const columnElement = board.find(`.board_column[data-ident='${column}']`);\n columnElement.detach().appendTo(board);\n });\n } else if (item.action == 'update_column') {\n $(\".board_column[data-ident='\" + data.id + \"'] .mod_board_column_name\").html(data.name);\n updateColumnAria(data.id);\n } else if (item.action == 'lock_column') {\n $(\".board_column[data-ident='\" + data.id + \"']\").attr(\"data-locked\", data.locked);\n if (data.locked) {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').addClass('d-none');\n } else {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').removeClass('d-none');\n }\n updateSortable();\n } else if (item.action == 'delete_column') {\n var column = $(\".board_column[data-ident='\" + data.id + \"']\");\n if (editingNote && column.find('.board_note[data-ident=\"' + editingNote + '\"]').length) {\n stopNoteEdit();\n }\n column.remove();\n } else if (item.action == 'rate_note') {\n var note = getNote(data.id);\n note.find('.mod_board_rating').html(data.rating);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n lastHistoryId = item.id;\n }\n\n updateBoard();\n });\n };\n\n /**\n * Trigger a board update.\n *\n * @method updateBoard\n * @param {boolean} instant\n */\n var updateBoard = function(instant) {\n if (instant) {\n processBoardHistory();\n } else if (options.history_refresh > 0) {\n if (reloadTimer) {\n stopUpdating();\n }\n reloadTimer = setTimeout(processBoardHistory, options.history_refresh * 1000);\n }\n };\n\n /**\n * Stop/prevent the board reload timer from firing.\n *\n * @method stopUpdating\n */\n var stopUpdating = function() {\n clearTimeout(reloadTimer);\n reloadTimer = null;\n };\n\n /**\n * Sort a set of notes.\n *\n * @sortNotes\n * @param {string} content\n * @param {boolean} toggle\n */\n var sortNotes = function(content, toggle) {\n var sortCol = $(content).parent().find('.mod_board_column_sort'),\n direction = $(content).data('sort');\n if (!direction) {\n if (sortby == SORTBY_RATING) {\n direction = 'desc';\n } else {\n direction = 'asc';\n }\n }\n if (toggle) {\n direction = direction == 'asc' ? 'desc' : 'asc';\n }\n\n if (direction == 'asc') {\n sortCol.removeClass('fa-angle-down');\n sortCol.addClass('fa-angle-up');\n } else {\n sortCol.removeClass('fa-angle-up');\n sortCol.addClass('fa-angle-down');\n }\n $(content).data('sort', direction);\n\n var desc,\n asc;\n if (sortby == SORTBY_DATE) {\n desc = function(a, b) {\n return $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_RATING) {\n desc = function(a, b) {\n return $(b).find('.mod_board_rating').text() - $(a).find('.mod_board_rating').text() ||\n $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).find('.mod_board_rating').text() - $(b).find('.mod_board_rating').text() ||\n $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_NONE) {\n let sortElements = (a, b) => {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n $('> .board_note', $(content)).sort(sortElements).appendTo($(content));\n return;\n }\n\n $('> .board_note', $(content)).sort(direction === 'asc' ? asc : desc).appendTo($(content));\n\n };\n\n /**\n * Update sorting of sortable content.\n *\n * @method updateSortable\n */\n var updateSortable = function() {\n let fromColumnID;\n $(\".board_column[data-locked='false'] .board_column_content\").sortable({\n connectWith: \".board_column[data-locked='false'] .board_column_content\",\n cancel: \".mod_board_nosort\",\n handle: \".move_note\",\n start: function(_, ui) {\n fromColumnID = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n var note = $(ui.item),\n tocolumn = note.closest('.board_column'),\n elem = $(this),\n noteid = note.data('ident'),\n columnid = tocolumn.data('ident');\n let columnElements = tocolumn.find('.board_column_content').children();\n let sortorder = columnElements.index($(`.board_note[data-ident=${noteid}]`));\n let payload = {\n id: noteid,\n columnid: columnid,\n ownerid: ownerId,\n sortorder: sortorder\n };\n moveNote(fromColumnID, payload, elem);\n }\n });\n };\n\n /**\n * Move a note to a new position / column.\n *\n * @param {Int} fromColumnID The column the note is being moved from.\n * @param {Object} payload The payload to send to the server.\n * @param {Domnode} elem The element clicked to trigger the move.\n */\n const moveNote = (fromColumnID, payload, elem) => {\n updateSortOrders(fromColumnID, payload.columnid, payload.id, payload.sortorder);\n\n serviceCall('move_note', payload, (result) => {\n if (result.status) {\n lastHistoryId = result.historyid;\n updateNoteAria(payload.id);\n updateBoard();\n sortNotes($(`.board_column[data-ident=${payload.columnid}] .board_column_content`));\n } else {\n if (elem) {\n elem.sortable('cancel');\n }\n }\n });\n };\n\n /**\n * Enable column sorting\n */\n const columnSorting = () => {\n let movingColumnId;\n $(\".mod_board\").sortable({\n connectWith: \".mod_board\",\n axis: \"x\",\n containment: \".mod_board_wrapper\",\n cancel: \".mod_board_nosort\",\n handle: \".mod_column_move\",\n start: function(_, ui) {\n movingColumnId = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n let column = $(ui.item);\n let columns = $(\".mod_board\").find('.board_column');\n let sortorder = columns.index(column);\n let payload = {\n id: movingColumnId,\n sortorder: sortorder\n };\n moveColumn(payload);\n }\n });\n };\n\n /**\n * Move a column to a new position.\n *\n * @param {Object} payload The payload to send to the server.\n */\n const moveColumn = (payload) => {\n serviceCall('move_column', payload, false);\n };\n\n /**\n * Updates the inline data attributes necessary for rendering the lists\n * in the correct sort order. Note: the data attribute values updated by\n * jQuery are not reflected in DOM inspection but are still set.\n * @param {number} fromColumnID The column ID of the column to sort.\n * @param {number} toColumnID The column ID of the column to sort.\n * @param {number} noteID The note ID that was moved.\n * @param {number} newSortOrder The new position of the note sort order.\n */\n const updateSortOrders = (fromColumnID, toColumnID, noteID, newSortOrder) => {\n let toColumn = $(`.board_column[data-ident=${toColumnID}] .board_column_content`);\n let movedNote = $(`.board_note[data-ident=${noteID}]`);\n let oldSortOrder = movedNote.data('sortorder');\n // Check whether it is the same column and then increment or decrement notes above or below\n // then set sortorder according to whether the sortorder has moved up or down.\n let toChildren = toColumn.children();\n if (fromColumnID == toColumnID) {\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (oldSortOrder < newSortOrder) {\n if (sortOrder <= newSortOrder && sortOrder >= oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n } else if (oldSortOrder > newSortOrder) {\n if (sortOrder >= newSortOrder && sortOrder <= oldSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n }\n });\n } else {\n let fromColumn = $(`.board_column[data-ident=${fromColumnID}] .board_column_content`);\n let fromChildren = fromColumn.children();\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder >= newSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n });\n fromChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder > oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n });\n }\n movedNote.data('sortorder', newSortOrder);\n };\n\n /**\n * Get the body fragment for the modal form.\n *\n * @param {number} noteid\n * @param {number} columnid\n * @param {number} ownerId\n * @returns {Deferred|*}\n */\n var getBody = function(noteid, columnid, ownerId) {\n // Get the content of the modal.\n var params = {noteid: noteid, columnid: columnid, ownerid: ownerId};\n return Fragment.loadFragment('mod_board', 'note_form', contextid, params);\n };\n\n /**\n * Setup the aria labels for the modal.\n *\n * @param {object} note\n * @param {object} modal\n */\n var updateModalAria = function(note, modal) {\n let columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text(),\n addYoutube,\n addImage,\n addLink,\n postButton,\n cancelButton,\n modalRoot = modal.getRoot();\n\n if (note.data('ident')) {\n // Is a note update.\n var noteIdentifier = textIdentifierForNote(note);\n\n postButton = strings.aria_postedit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n cancelButton = strings.aria_canceledit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n addYoutube = strings.aria_addmedia.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addImage = strings.aria_addmedia.replace('{type}', strings.option_image).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addLink = strings.aria_addmedia.replace('{type}', strings.option_link).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n } else {\n // Note is new.\n postButton = strings.aria_postnew.replace('{column}', columnIdentifier);\n cancelButton = strings.aria_cancelnew.replace('{column}', columnIdentifier);\n addYoutube = strings.aria_addmedianew.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier);\n addImage = strings.aria_addmedianew.replace('{type}', strings.option_image).replace('{column}', columnIdentifier);\n addLink = strings.aria_addmedianew.replace('{type}', strings.option_link).replace('{column}', columnIdentifier);\n }\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('aria-label', addYoutube);\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('title', addYoutube);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('aria-label', addImage);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('title', addImage);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('aria-label', addLink);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('title', addLink);\n }\n\n let button = modalRoot.find(modal.getActionSelector('save'));\n if (button) {\n button.attr('aria-label', postButton);\n }\n button = modalRoot.find(modal.getActionSelector('cancel'));\n if (button) {\n button.attr('aria-label', cancelButton);\n }\n };\n\n /**\n * Displays the modal form to edit a note.\n *\n * @param {object} note\n */\n var showModalForm = function(note) {\n let noteId = 0,\n columnId = note.data('column'),\n column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n title;\n\n if (note.data('ident')) {\n noteId = note.data('ident');\n title = strings.modal_title_edit.replace('{column}', columnIdentifier);\n } else {\n title = strings.modal_title_new.replace('{column}', columnIdentifier);\n }\n\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: getBody(noteId, columnId, ownerId),\n large: true,\n removeOnClose: true\n }).then(function(modal) {\n // Use the body promise so we know body content is loaded.\n modal.getBodyPromise().then(function () {\n let saveInProgress = false;\n editModal = modal;\n modal.setLarge();\n modal.setSaveButtonText(strings.post_button_text);\n modal.setButtonText('cancel', strings.cancel_button_text);\n\n modal.getRoot().on(ModalEvents.hidden, function () {\n stopNoteEdit();\n if (!note.data('ident')) {\n note.remove();\n }\n });\n\n modal.getRoot().on(ModalEvents.save, function (e) {\n e.preventDefault();\n modal.getRoot().find('form').submit();\n });\n\n var changeEvent = document.createEvent('HTMLEvents');\n changeEvent.initEvent('change', true, true);\n\n modal.getRoot().on('submit', 'form', function (e) {\n e.preventDefault();\n\n // Prevent multiple form submissions from being sent.\n if (saveInProgress) {\n return;\n }\n saveInProgress = true;\n\n // First, make sure the native html5 validity checks are run.\n let valid = modal.getRoot().find('form').get(0).reportValidity();\n if (!valid) {\n saveInProgress = false;\n return;\n }\n\n // Prompt all inputs to run their validation functions.\n // Normally this would happen when the form is submitted, but\n // since we aren't submitting the form normally we need to run client side\n // validation.\n modal.getRoot().find(':input').each(function (index, element) {\n element.dispatchEvent(changeEvent);\n });\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n var invalid = $.merge(\n modal.getRoot().find('[aria-invalid=\"true\"]'),\n modal.getRoot().find('.error'),\n modal.getRoot().find(':invalid')\n );\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n saveInProgress = false;\n return;\n }\n\n var formData = JSON.stringify(modal.getRoot().find('form').serialize());\n serviceCall('submit_form', {contextid: contextid, jsonformdata: formData}, function (result) {\n if (result.status) {\n if (result.action == 'insert') {\n // Added a new note.\n lastHistoryId = result.historyid;\n note.remove();\n addNote(columnId, result.note.id, result.note.heading, result.note.content,\n {type: result.note.type, info: result.note.info, url: result.note.url},\n {id: result.note.userid}, result.note.timecreated, result.note.rating);\n sortNotes($('.board_column[data-ident=' + columnId + '] .board_column_content'));\n updateNoteAria(result.note.id);\n } else {\n // Updated existing note.\n lastHistoryId = result.historyid;\n getNoteTextForNote(note).html(result.note.content);\n getNoteHeadingForNote(note).html(result.note.heading);\n updateNoteAria(result.note.id);\n setAttachment(note, {\n type: result.note.type,\n info: result.note.info, url: result.note.url\n });\n }\n stopNoteEdit();\n\n // Clear the form changed checker.\n Y.use('moodle-core-formchangechecker', function() {\n M.core_formchangechecker.reset_form_dirty_state();\n });\n\n modal.destroy();\n } else {\n modal.destroy();\n }\n });\n\n });\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n // First hide the select menu.\n modal.getRoot().find('#fitem_id_mediatype').hide();\n\n let mediaSelect = modal.getRoot().find('#fitem_id_mediatype select'),\n ytButton = modal.getRoot().find('.mod_board_attachment_button.youtube_button'),\n pictureButton = modal.getRoot().find('.mod_board_attachment_button.image_button'),\n linkButton = modal.getRoot().find('.mod_board_attachment_button.link_button'),\n updateMediaButtons = function() {\n ytButton.removeClass('selected');\n pictureButton.removeClass('selected');\n linkButton.removeClass('selected');\n switch (mediaSelect.val()) {\n case (\"1\"):\n ytButton.addClass('selected');\n break;\n case (\"2\"):\n pictureButton.addClass('selected');\n break;\n case (\"3\"):\n linkButton.addClass('selected');\n break;\n }\n };\n\n updateMediaButtons();\n handleAction(ytButton, function() {\n if (mediaSelect.val() === \"1\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(1);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(pictureButton, function() {\n if (mediaSelect.val() === \"2\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(2);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(linkButton, function() {\n if (mediaSelect.val() === \"3\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(3);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n } else {\n modal.getRoot().find('#fitem_id_mediabuttons').hide();\n }\n\n updateModalAria(note, modal);\n modal.show();\n\n return modal;\n }).catch(Notification.exception);\n return modal;\n }).catch(Notification.exception);\n };\n\n /**\n * Show the note in a modal\n * @param {Int} ident The note id\n * @param {Object} notecontent The note content\n */\n var fullScreenNote = (ident, notecontent) => {\n const heading = getNoteHeadingForNote(notecontent).html();\n const modalBody = $(document.createElement('div'));\n modalBody.addClass('mod_board_note_content');\n const text = getNoteTextForNote(notecontent);\n if (text) {\n modalBody.append(text.clone());\n }\n const preview = getNotePreviewForNote(notecontent);\n if (preview) {\n modalBody.append(preview.clone());\n }\n\n // Adds the comments to a note.\n const commentArea = $(document.createElement('div'));\n commentArea.attr('data-region', 'comment-area');\n modalBody.append(commentArea);\n Comments.fetchFor(ident, commentArea);\n\n ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: heading,\n body: modalBody,\n }).then(function(modal) {\n modal.setLarge();\n modal.show();\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function () {\n // Destroy when hidden.\n modal.destroy();\n });\n return modal;\n }, this).catch(Notification.exception);\n };\n\n /**\n * Initialize board.\n *\n * @method init\n */\n var init = function() {\n serviceCall('get_board', {id: board.id, ownerid: ownerId}, function(columns) {\n // Init\n if (columns) {\n for (var index in columns) {\n addColumn(\n columns[index].id,\n columns[index].name,\n columns[index].locked,\n columns[index].notes || {},\n options.colours[columns[index].id % options.colours.length]\n );\n }\n }\n\n if (isEditor) {\n addNewColumnButton();\n }\n\n lastHistoryId = board.historyid;\n\n if (isEditor) {\n updateSortable();\n columnSorting();\n }\n\n updateBoard();\n });\n };\n\n // Get strings\n var stringsInfo = [];\n for (var string in strings) {\n stringsInfo.push({key: string, component: 'mod_board'});\n }\n\n $.when(getStrings(stringsInfo)).done(function(results) {\n var index = 0;\n for (string in strings) {\n strings[string] = results[index++];\n }\n\n init();\n });\n}\n"],"names":["settings","strings","default_column_heading","post_button_text","cancel_button_text","remove_note_title","remove_note_text","remove_column_title","note_changed_title","note_changed_text","note_deleted_text","rate_note_title","rate_note_text","rate_remove_note_text","Ok","delete","Cancel","warning","modal_title_new","modal_title_edit","option_youtube","option_image","option_link","aria_newcolumn","aria_newpost","aria_deletecolumn","aria_movecolumn","aria_deletepost","aria_movepost","aria_editpost","aria_addmedia","aria_addmedianew","aria_deleteattachment","aria_postedit","aria_canceledit","aria_postnew","aria_cancelnew","aria_ratepost","invalid_file_extension","invalid_file_size_min","invalid_file_size_max","invalid_youtube_url","options","JSON","parse","board","contextid","reloadTimer","lastHistoryId","isEditor","usersCanEdit","userId","parseInt","userFirstname","firstname","userLastname","lastname","ownerId","mediaSelection","mediaselection","editingNote","isReadOnlyBoard","readonly","showauthorofnote","ratingenabled","sortby","editModal","enableblanktarget","serviceCall","method","args","callback","failcallback","stopUpdating","call","methodname","done","data","fail","error","exception","_serviceCall","apply","arguments","updateBoard","getNote","ident","getNoteTextForNote","note","find","getNoteHeadingForNote","getNoteBorderForNote","getNoteAttachmentsForNote","textIdentifierForNote","noteText","html","noteHeading","noteAttachment","attachmentDataForNote","length","replace","split","slice","join","info","updateNoteAria","noteId","columnIdentifier","closest","text","noteIdentifier","deleteNoteString","attr","moveNoteString","editNoteString","updateColumnAria","columnId","column","newNoteString","moveColumnString","deleteColumnString","each","index","stopNoteEdit","noteBorder","show","hide","remove","sortAfterDelete","columnID","sortorder","getColumn","children","filter","_","element","so","setAttachment","attachment","type","attType","val","decodeText","url","attachmentInfo","attachmentUrl","attachmentFile","prop","attachmentTypeToString","FileReader","attachmentTypeChanged","previewAttachment","filename","filecontents","encodeText","fileElem","elem","removeClass","addClass","blanktarget","videoID","match","undefined","getEmbedUrl","addNote","columnid","heading","content","owner","rating","ismynote","id","iseditable","pendingNote","notecontent","notecontrols","noteAuthorusername","noteAriaText","attachmentPreview","append","columnContent","beginEdit","showModalForm","startNoteEdit","rateElement","handleAction","result","canrate","rateRemoveText","hasrated","confirm","status","historyid","sortNotes","then","rateModal","getRoot","on","ModalEvents","hidden","rateNote","removeElement","deleteNote","moveElement","init","moveNote","editElement","updateSortable","fullScreenNote","lastOne","last","insertAfter","prepend","addColumn","name","locked","notes","colour","headerStyle","nameCache","columnHeader","columnSort","columnName","columnNewContent","hideheaders","lockIcon","lockElement","lockstring","str","lockColumn","moveColumn","getColumnName","callBeforeOnKeyEditing","is","Error","e","isAriaTriggerKey","keyCode","preventDefault","editable","handleEditableAction","toggleFontSize","closeOnEnter","newNoteButton","noteicon","timecreated","userid","columnSorting","selectHeadingColour","colCount","colourCount","colours","updateNote","processBoardHistory","ownerid","since","boardhistory","item","boardid","action","formModal","historyData","alert","forEach","detach","appendTo","instant","history_refresh","setTimeout","clearTimeout","toggle","desc","asc","sortCol","parent","direction","a","b","sortElements","sort","fromColumnID","sortable","connectWith","cancel","handle","start","ui","stop","tocolumn","this","noteid","payload","updateSortOrders","movingColumnId","axis","containment","toColumnID","noteID","newSortOrder","toColumn","movedNote","oldSortOrder","toChildren","sortOrder","fromChildren","getBody","params","Fragment","loadFragment","title","create","ModalFactory","types","SAVE_CANCEL","body","large","removeOnClose","modal","getBodyPromise","saveInProgress","setLarge","setSaveButtonText","setButtonText","save","submit","changeEvent","document","createEvent","initEvent","get","reportValidity","dispatchEvent","invalid","$","merge","first","focus","formData","stringify","serialize","jsonformdata","Y","use","M","core_formchangechecker","reset_form_dirty_state","destroy","mediaSelect","ytButton","pictureButton","linkButton","updateMediaButtons","addYoutube","addImage","addLink","postButton","cancelButton","modalRoot","button","getActionSelector","updateModalAria","catch","Notification","modalBody","createElement","clone","preview","commentArea","fetchFor","CANCEL","columns","newBusy","columnicon","stringsInfo","string","push","key","component","when","results","rawText","encodedText"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/board.js b/amd/src/board.js index f975d10..c43b3ce 100755 --- a/amd/src/board.js +++ b/amd/src/board.js @@ -218,10 +218,13 @@ export default function(settings) { isEditor = options.isEditor || false, usersCanEdit = options.usersCanEdit, userId = parseInt(options.userId) || -1, + userFirstname = options.firstname, + userLastname = options.lastname, ownerId = parseInt(options.ownerId), mediaSelection = options.mediaselection || MEDIA_SELECTION_BUTTONS, editingNote = 0, isReadOnlyBoard = options.readonly || false, + showauthorofnote = options.showauthorofnote || false, ratingenabled = options.ratingenabled, sortby = options.sortby || SORTBY_DATE, editModal = null, @@ -795,12 +798,37 @@ export default function(settings) { var notecontent = $('
'), notecontrols = $('
'), noteHeading = $('
' + (heading ? heading : '') + '
'), + noteAuthorusername = $(''), noteBorder = $('
'), noteText = $('
' + (content ? content : '') + '
'), noteAriaText = $(''), attachmentPreview = $('
'); + if (showauthorofnote) { + let firstname = ''; + let lastname = ''; + if (ismynote) { + // Use the Name of the user itself. We do not need to get this information from somewhere else. + firstname = userFirstname; + lastname = userLastname; + } else { + firstname = owner.firstname; + lastname = owner.lastname; + } + + noteAuthorusername = '
' + + ' ' + + '' + + firstname + + '' + + '' + + lastname + + '' + + '
' ; + } + notecontent.append(noteHeading); + notecontent.append(noteAuthorusername); notecontent.append(noteBorder); notecontent.append(noteText); notecontent.append(noteAriaText); @@ -1019,6 +1047,7 @@ export default function(settings) { newNoteButton.addClass('d-none'); } handleAction(columnNewContent.find('.newnote'), function() { + // We do not need to add firstname and lasname because we use ismynote and actual board user. addNote(ident, 0, null, null, null, {id: userId}, 0, 0); }); } @@ -1033,9 +1062,11 @@ export default function(settings) { if (notes) { for (var index in notes) { let sortorder = sortby == 3 ? notes[index].sortorder : notes[index].timecreated; + addNote(ident, notes[index].id, notes[index].heading, notes[index].content, {type: notes[index].type, info: notes[index].info, url: notes[index].url}, - {id: notes[index].userid}, sortorder, notes[index].rating); + {id: notes[index].userid, firstname: notes[index].firstname, lastname: notes[index].lastname}, + sortorder, notes[index].rating); } } sortNotes(columnContent); diff --git a/backup/moodle2/backup_board_stepslib.php b/backup/moodle2/backup_board_stepslib.php index 3779218..4084c0e 100755 --- a/backup/moodle2/backup_board_stepslib.php +++ b/backup/moodle2/backup_board_stepslib.php @@ -31,10 +31,9 @@ protected function define_structure() { $userinfo = $this->get_setting_value('userinfo'); - $board = new backup_nested_element('board', array('id'), array( - 'course', 'name', 'timemodified', 'intro', 'introformat', 'historyid', - 'background_color', 'addrating', 'hideheaders', 'sortby', 'postby', 'userscanedit', 'singleusermode', - 'completionnotes')); + $board = new backup_nested_element('board', array('id'), array('course', 'name', 'timemodified', 'intro', 'introformat', + 'historyid', 'background_color', 'showauthorofnote', 'addrating', 'hideheaders', 'sortby', 'postby', + 'userscanedit', 'singleusermode', 'completionnotes')); $columns = new backup_nested_element('columns'); $column = new backup_nested_element('column', array('id'), array('boardid', 'name', 'sortorder')); diff --git a/classes/board.php b/classes/board.php index 25dcdab..4feeda8 100644 --- a/classes/board.php +++ b/classes/board.php @@ -101,6 +101,8 @@ public static function get_configuration($id, $ownerid) { 'isEditor' => self::board_is_editor($board->id), 'usersCanEdit' => self::board_users_can_edit($board->id), 'userId' => $USER->id, + 'firstname' => $USER->firstname, + 'lastname' => $USER->lastname, 'ownerId' => $ownerid, 'readonly' => (self::board_readonly($board->id) || !self::can_post($board->id, $USER->id, $ownerid)), 'columnicon' => $config->new_column_icon, @@ -113,6 +115,7 @@ public static function get_configuration($id, $ownerid) { 'size_min' => self::ACCEPTED_FILE_MIN_SIZE, 'size_max' => self::ACCEPTED_FILE_MAX_SIZE ], + 'showauthorofnote' => self::board_show_authorofnote($board->id), 'ratingenabled' => self::board_rating_enabled($board->id), 'hideheaders' => self::board_hide_headers($board->id), 'sortby' => $board->sortby, @@ -372,6 +375,19 @@ public static function board_get(int $boardid, int $ownerid = 0): array { $column->notes = $DB->get_records('board_notes', $params, 'sortorder', 'id, userid, heading, content, type, info, url, timecreated, sortorder'); + + // Add the name of the author of a note to the note-object. + foreach ($column->notes as $colid => $note) { + if (self::board_show_authorofnote($board->id)) { + $authorofnote = static::get_authorofnote($note->userid); + $note->firstname = $authorofnote['firstname']; + $note->lastname = $authorofnote['lastname']; + } else { + $note->firstname = ''; + $note->lastname = ''; + } + } + foreach ($column->notes as $colid => $note) { $note->rating = static::get_note_rating($note->id); } @@ -381,6 +397,21 @@ public static function board_get(int $boardid, int $ownerid = 0): array { return $columns; } + /** + * Gets the author/user (including firstname and lastname) of a note. + * + * @param int $userid The userid of the author of a note. + * @return array + */ + public static function get_authorofnote($userid): array { + global $DB; + $user = $DB->get_record('user', ['id' => $userid], 'firstname, lastname'); + $authorofnote = []; + $authorofnote['firstname'] = $user->firstname; + $authorofnote['lastname'] = $user->lastname; + return $authorofnote; + } + /** * Retrieves the boards history. * @@ -1147,6 +1178,21 @@ public static function board_move_note_log($boardid, $columnid, $noteid) { $event->trigger(); } + /** + * Checks to see if showauthorofnote has been enabled for the board. + * + * @param int $boardid + * @return bool + */ + public static function board_show_authorofnote($boardid) { + $board = static::get_board($boardid); + if (!$board) { + return false; + } + + return !empty($board->showauthorofnote); + } + /** * Checks to see if the user can rate the note. * diff --git a/db/install.xml b/db/install.xml index 245f594..efb5591 100755 --- a/db/install.xml +++ b/db/install.xml @@ -14,6 +14,7 @@ + diff --git a/db/upgrade.php b/db/upgrade.php index 64b0180..0f62640 100755 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -235,5 +235,20 @@ function xmldb_board_upgrade(int $oldversion) { upgrade_mod_savepoint(true, 2022040110, 'board'); } + if ($oldversion < 2022040112) { + + // Define field showauthorofnote to be added to board_notes. + $table = new xmldb_table('board'); + $field = new xmldb_field('showauthorofnote', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'background_color'); + + // Conditionally launch add field sortorder. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Board savepoint reached. + upgrade_mod_savepoint(true, 2022040112, 'board'); + } + return true; } diff --git a/external.php b/external.php index 259e885..a17496b 100755 --- a/external.php +++ b/external.php @@ -129,6 +129,8 @@ public static function get_board_returns(): external_multiple_structure { array( 'id' => new external_value(PARAM_INT, 'post id'), 'userid' => new external_value(PARAM_INT, 'user id'), + 'firstname' => new external_value(PARAM_TEXT, 'user firstname'), + 'lastname' => new external_value(PARAM_TEXT, 'user lastname'), 'heading' => new external_value(PARAM_TEXT, 'post heading'), 'content' => new external_value(PARAM_RAW, 'post content'), 'type' => new external_value(PARAM_INT, 'type'), diff --git a/lang/en/board.php b/lang/en/board.php index bf19c6a..7374eed 100755 --- a/lang/en/board.php +++ b/lang/en/board.php @@ -246,3 +246,12 @@ $string['singleusermodenotembed'] = 'Board does not allow a single user board to be embedded. Please change your settings.'; $string['allowed_singleuser_modes'] = 'Enabled single user modes'; $string['allowed_singleuser_modes_desc'] = 'Allow/Disallow usage of certain single user modes. Does not affect already created boards'; + +$string['showauthorofnoteinfoenabled'] = 'Show author of note is enabled.'; +$string['showauthorofnoteinfodisabled'] = 'Show author of note is disabled but can be later activated to see the owner of notes.'; + +$string['showauthorofnote'] = 'Show author of notes.'; +$string['showauthorofnote_help'] = 'If activated, then the information, that authors of notes are displayed will be show above the board. If inactive, then the information "showauthorofnoteinfodisabled" is displayed to inform the user that the authot of a note might be visible if teacher later activates the feature.'; + +$string['adminsetting:allowshowauthorofnoteonboard'] = 'Allow to activate to show author of note on boards'; +$string['adminsetting:allowshowauthorofnoteonboard_desc'] = 'If activated the board can be configured to show the author of a note on the board or the author can be hidden to students (Teacher can see owner of note by using the export).'; diff --git a/mod_form.php b/mod_form.php index 7197e47..aa1f918 100755 --- a/mod_form.php +++ b/mod_form.php @@ -70,6 +70,11 @@ public function definition() { $mform->addElement('filemanager', 'background_image', get_string('background_image', 'mod_board'), null, $filemanageroptions); + $mform->addElement('advcheckbox', 'showauthorofnote', get_string('showauthorofnote', 'mod_board')); + $mform->addHelpButton('showauthorofnote', 'showauthorofnote', 'mod_board'); + $mform->setDefault('showauthorofnote', 0); + $mform->setType('showauthorofnote', PARAM_INT); + $mform->addElement('select', 'addrating', get_string('addrating', 'mod_board'), array( board::RATINGDISABLED => get_string('addrating_none', 'mod_board'), diff --git a/scss/styles.scss b/scss/styles.scss index 948a5eb..589993e 100644 --- a/scss/styles.scss +++ b/scss/styles.scss @@ -145,6 +145,17 @@ padding: 0; margin: 0; } + + .mod_board_note_author { + .mod_board_note_author_firstname { + color: #12129a; + } + .mod_board_note_author_lastname { + margin-left: 3px; + color: #12129a; + } + } + .mod_board_note_attachment { padding-top: 10px; margin: 0; diff --git a/settings.php b/settings.php index 0e4dd0c..c7e9733 100755 --- a/settings.php +++ b/settings.php @@ -67,6 +67,13 @@ '1' )); + $settings->add(new admin_setting_configcheckbox( + 'mod_board/allowshowauthorofnoteonboard', + get_string('adminsetting:allowshowauthorofnoteonboard', 'mod_board'), + get_string('adminsetting:allowshowauthorofnoteonboard_desc', 'mod_board'), + '0' + )); + $settings->add(new admin_setting_configtext('mod_board/embed_width', get_string('embed_width', 'mod_board'), get_string('embed_width_desc', 'mod_board'), '99%', PARAM_TEXT)); diff --git a/styles.css b/styles.css index 0883f91..a8dae86 100755 --- a/styles.css +++ b/styles.css @@ -169,6 +169,15 @@ max-width: initial; } +.mod_board .mod_board_note_content .mod_board_note_author .mod_board_note_author_firstname { + color: #12129a; +} + +.mod_board .mod_board_note_content .mod_board_note_author .mod_board_note_author_lastname { + margin-left: 3px; + color: #12129a; +} + .mod_board .mod_board_rating { color: #333; margin-top: 10px; diff --git a/tests/board_test.php b/tests/board_test.php index b80dcc6..8c64a31 100644 --- a/tests/board_test.php +++ b/tests/board_test.php @@ -447,6 +447,7 @@ private static function add_board(int $courseid) { 'intro' => '', 'historyid' => 3, 'background_color' => null, + 'showauthorofnote' => 0, 'addrating' => 3, 'hideheaders' => 0, 'sortby' => 2, diff --git a/version.php b/version.php index b317ab2..bfa51b4 100755 --- a/version.php +++ b/version.php @@ -25,7 +25,8 @@ defined('MOODLE_INTERNAL') || die; $plugin->component = 'mod_board'; // Full name of the plugin (used for diagnostics). -$plugin->version = 2022040110; // The current module version Use 2022.04.01 as base for 4.00. -$plugin->requires = 2022041900; // Moodle 4.00 and up. +// $plugin->version = 2022040110; // The current module version Use 2022.04.01 as base for 4.00. +$plugin->version = 2022040112; // 2022040112 for developing the new feature "show author of note", should be adapted +$plugin->requires = 2022041900; // Moodle 4.00 and up. $plugin->release = '1.401.00 (Build 2022121200)'; -$plugin->maturity = MATURITY_BETA; +$plugin->maturity = MATURITY_BETA; diff --git a/view.php b/view.php index 1b29474..a6e1c99 100755 --- a/view.php +++ b/view.php @@ -81,7 +81,7 @@ $PAGE->requires->js_call_amd('mod_board/main', 'initialize', [ 'boardid' => $board->id, - 'ownerid' => $ownerid + 'ownerid' => $ownerid, ] ); @@ -100,6 +100,12 @@ echo html_writer::tag('div', get_string('blanktargetenabled', 'mod_board'), ['class' => 'small']); } +if ($board->showauthorofnote) { + echo html_writer::tag('div', get_string('showauthorofnoteinfoenabled', 'mod_board'), ['class' => 'small']); +} else { + echo html_writer::tag('div', get_string('showauthorofnoteinfodisabled', 'mod_board'), ['class' => 'small']); +} + echo $OUTPUT->box_start('mod_introbox', 'group_menu'); echo groups_print_activity_menu($cm, $pageurl, true); echo $OUTPUT->box_end(); @@ -150,7 +156,7 @@ ['style' => 'display: block !important; width: 140px;']); $img .= html_writer::tag('span', get_string('opensinnewwindow', 'mod_board'), ['class' => 'sr-only']); echo html_writer::link('https://www.brickfield.ie/docs/mod_board/', $img, ['target' => '_blank', - 'style' => 'margin-left: auto; margin-right: 90px; display: block !important; width: 140px;']); + 'style' => 'margin-left: auto; margin-right: 90px; display: block !important; width: 140px;', ]); } echo '
'; } From 5975e899788c61bcca7d26d5a07ad936c151dbf5 Mon Sep 17 00:00:00 2001 From: Andreas Schenkel Date: Wed, 13 Dec 2023 09:17:01 +0100 Subject: [PATCH 2/6] use fullname instead of firstname lastname; fix: (alphaversion) websiteadminsetting to activate or deactivate feature for the moodle instance --- amd/build/board.min.js | 2 +- amd/build/board.min.js.map | 2 +- amd/src/board.js | 30 ++++++++++++------------------ classes/board.php | 37 +++++++++++++------------------------ external.php | 3 +-- scss/styles.scss | 5 +---- styles.css | 6 +----- view.php | 11 +++++++++++ 8 files changed, 41 insertions(+), 55 deletions(-) diff --git a/amd/build/board.min.js b/amd/build/board.min.js index cab5332..22075a9 100755 --- a/amd/build/board.min.js +++ b/amd/build/board.min.js @@ -5,6 +5,6 @@ define("mod_board/board",["exports","jquery","core/str","core/ajax","core/modal_ * @author Karen Holland * @copyrigt 2021 Brickfield Education Labs * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=function(settings){var strings={default_column_heading:"",post_button_text:"",cancel_button_text:"",remove_note_title:"",remove_note_text:"",remove_column_title:"",note_changed_title:"",note_changed_text:"",note_deleted_text:"",rate_note_title:"",rate_note_text:"",rate_remove_note_text:"",Ok:"",delete:"",Cancel:"",warning:"",modal_title_new:"",modal_title_edit:"",option_youtube:"",option_image:"",option_link:"",aria_newcolumn:"",aria_newpost:"",aria_deletecolumn:"",aria_movecolumn:"",aria_deletepost:"",aria_movepost:"",aria_editpost:"",aria_addmedia:"",aria_addmedianew:"",aria_deleteattachment:"",aria_postedit:"",aria_canceledit:"",aria_postnew:"",aria_cancelnew:"",aria_ratepost:"",invalid_file_extension:"",invalid_file_size_min:"",invalid_file_size_max:"",invalid_youtube_url:""},options=JSON.parse(settings.settings)||{},board=options.board||{},contextid=options.contextid;var reloadTimer=null,lastHistoryId=null,isEditor=options.isEditor||!1,usersCanEdit=options.usersCanEdit,userId=parseInt(options.userId)||-1,userFirstname=options.firstname,userLastname=options.lastname,ownerId=parseInt(options.ownerId),mediaSelection=options.mediaselection||1,editingNote=0,isReadOnlyBoard=options.readonly||!1,showauthorofnote=options.showauthorofnote||!1,ratingenabled=options.ratingenabled,sortby=options.sortby||1,editModal=null,enableblanktarget=1===parseInt(options.enableblanktarget),serviceCall=function(method,args,callback,failcallback){"board_history"!==method&&stopUpdating(),function(method,args,callback,failcallback){_ajax.default.call([{methodname:"mod_board_"+method,args:args,done:function(data){callback(data)},fail:function(error){_notification.default.exception(error),failcallback&&failcallback(error)}}])}(method,args,(function(){callback&&callback.apply(null,arguments),"board_history"!==method&&"get_board"!=method&&updateBoard(!0)}),failcallback)},getNote=function(ident){return(0,_jquery.default)(".board_note[data-ident='"+ident+"']")},getNoteTextForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_text")},getNoteHeadingForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_heading")},getNoteBorderForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_border")},getNoteAttachmentsForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_attachment")},textIdentifierForNote=function(note){var noteText=getNoteTextForNote(note).html(),noteHeading=getNoteHeadingForNote(note).html(),noteAttachment=attachmentDataForNote(note);return noteHeading.length>0?noteHeading:noteText.length>0?noteText.replace(//gi," ").replace(/\n/g," ").split(/\s+/).slice(0,5).join(" "):noteAttachment.info&¬eAttachment.info.length>0?noteAttachment.info:null},updateNoteAria=function(noteId){var note=getNote(noteId),columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text();if(noteId){var noteIdentifier=textIdentifierForNote(note),deleteNoteString=strings.aria_deletepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier);note.find(".delete_note").attr("aria-label",deleteNoteString).attr("title",deleteNoteString);var moveNoteString=strings.aria_movepost.replace("{post}",noteIdentifier);note.find(".move_note").attr("aria-label",moveNoteString).attr("title",moveNoteString);var editNoteString=strings.aria_editpost.replace("{post}",noteIdentifier);note.find(".edit_note").attr("aria-label",editNoteString).attr("title",editNoteString),note.find(".mod_board_rating").attr("aria-label",strings.aria_ratepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)),note.find(".note_ariatext").html(noteIdentifier)}},updateColumnAria=function(columnId){var column=(0,_jquery.default)(".board_column[data-ident="+columnId+"]"),columnIdentifier=column.find(".mod_board_column_name").text(),newNoteString=strings.aria_newpost.replace("{column}",columnIdentifier),moveColumnString=strings.aria_movecolumn.replace("{column}",columnIdentifier),deleteColumnString=strings.aria_deletecolumn.replace("{column}",columnIdentifier);column.find(".newnote").attr("aria-label",newNoteString).attr("title",newNoteString),column.find(".mod_column_move").attr("aria-label",moveColumnString).attr("title",moveColumnString),column.find(".delete_column").attr("aria-label",deleteColumnString).attr("title",deleteColumnString),column.find(".board_note").each((function(index,note){updateNoteAria((0,_jquery.default)(note).data("ident"))}))},stopNoteEdit=function(){if(editingNote){var note=getNote(editingNote);if(note){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())}editingNote=0}else getNote(0).remove()};const sortAfterDelete=(columnID,sortorder)=>{let column=(columnID=>(0,_jquery.default)(".board_column[data-ident='".concat(columnID,"'] .board_column_content")))(columnID);column.children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so-1)}))};var setAttachment=function(note,attachment){var noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment){attachment?attachment.type+="":attachment={type:"0"};var attType=noteAttachment.find(".mod_board_type");attType.val(attachment.type?attachment.type:"0"),attType.val()>"0"&&(noteAttachment.find(".info").val(decodeText(attachment.info)),noteAttachment.find(".url").val(decodeText(attachment.url))),function(note){var noteAttachment=getNoteAttachmentsForNote(note),type=noteAttachment.find(".mod_board_type").val(),attachmentInfo=noteAttachment.find(".info"),attachmentUrl=noteAttachment.find(".url"),attachmentFile=noteAttachment.find(".mod_board_file");type>"0"?(attachmentInfo.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_info"]),attachmentUrl.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_url"]),attachmentInfo.show(),2==type&&FileReader?(attachmentFile.show(),attachmentUrl.hide()):(attachmentFile.hide(),attachmentUrl.show())):(attachmentInfo.hide(),attachmentUrl.hide(),attachmentFile.hide(),attachmentInfo.val(""),attachmentUrl.val(""))}(note)}previewAttachment(note,attachment)},attachmentDataForNote=function(note){var attachment={type:0,info:null,url:null,filename:null,filecontents:null},noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment.length){attachment.type=noteAttachment.find(".mod_board_type").val(),attachment.info=encodeText(noteAttachment.find(".info").val()),attachment.url=encodeText(noteAttachment.find(".url").val());var fileElem=noteAttachment.find(".mod_board_file>input");fileElem.data("filename")&&(attachment.filename=fileElem.data("filename"),attachment.filecontents=fileElem.data("filecontents"))}return attachment.info&&attachment.info.length||attachment.url&&attachment.url.length||attachment.filename||(attachment.type=0),attachment},attachmentTypeToString=function(type){switch(type){case"1":return"youtube";case"2":return"image";case"3":return"link";default:return null}};var previewAttachment=function(note,attachment){var elem=note.find(".mod_board_preview");if(attachment||(attachment=attachmentDataForNote(note)),getNoteTextForNote(note).html().length?elem.removeClass("mod_board_notext"):elem.addClass("mod_board_notext"),elem.removeClass("wrapper_youtube"),elem.removeClass("wrapper_image"),elem.removeClass("wrapper_url"),attachment.filename&&2==parseInt(attachment.type))elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();else if(attachment.url){const blanktarget=enableblanktarget?' target="_blank"':"";switch(parseInt(attachment.type)){case 1:{let url=(url=>{let videoID=url.match(/(\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/);return videoID&&void 0!==videoID[2]&&11===videoID[2].length?"https://www.youtube-nocookie.com/embed/".concat(videoID[2]):null})(attachment.url);null===url?elem.html(strings.invalid_youtube_url):(elem.html(''),elem.addClass("wrapper_youtube").addClass("position-relative")),elem.show()}break;case 2:elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();break;case 3:elem.html('"+(attachment.info||attachment.url)+""),elem.addClass("wrapper_url"),elem.show();break;default:elem.html(""),elem.hide()}}else elem.html(""),elem.hide()},addNote=function(columnid,ident,heading,content,attachment,owner,sortorder,rating){var ismynote=owner.id==userId||!ident,iseditable=isEditor||ismynote&&!isReadOnlyBoard;if(!ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}if(3==sortby){(0,_jquery.default)(".board_column[data-ident='".concat(columnid,"'] .board_column_content")).children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>=parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so+1)}))}var note=(0,_jquery.default)('
');ismynote&¬e.addClass("mod_board_mynote"),iseditable&¬e.addClass("mod_board_editablenote"),ismynote||iseditable||note.addClass("mod_board_nosort");var notecontent=(0,_jquery.default)('
'),notecontrols=(0,_jquery.default)('
'),noteHeading=(0,_jquery.default)('
'+(heading||"")+"
"),noteAuthorusername=(0,_jquery.default)(""),noteBorder=(0,_jquery.default)('
'),noteText=(0,_jquery.default)('
'+(content||"")+"
"),noteAriaText=(0,_jquery.default)(''),attachmentPreview=(0,_jquery.default)('
');if(showauthorofnote){let firstname="",lastname="";ismynote?(firstname=userFirstname,lastname=userLastname):(firstname=owner.firstname,lastname=owner.lastname),noteAuthorusername='
'+firstname+''+lastname+"
"}notecontent.append(noteHeading),notecontent.append(noteAuthorusername),notecontent.append(noteBorder),notecontent.append(noteText),notecontent.append(noteAriaText),notecontent.append(attachmentPreview),note.append(notecontent);var columnContent=(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_content"),beginEdit=()=>{!function(ident){if(editingNote){if(editingNote==ident)return;stopNoteEdit()}if(ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}var note=getNote(ident);note&&(showModalForm(note),ident&&(editingNote=ident))}(ident)};if(ident){if(ratingenabled){note.addClass("mod_board_rateablenote");var rateElement=(0,_jquery.default)('
'.concat(rating,"
"));handleAction(rateElement,(()=>{!function(ident){if(ratingenabled&&!isReadOnlyBoard){var note=getNote(ident),rating=note.find(".mod_board_rating");rating.data("disabled")||(rating.data("disabled",!0),serviceCall("can_rate_note",{id:ident},(function(result){if(result.canrate){const rateRemoveText=result.hasrated?strings.rate_remove_note_text:strings.rate_note_text;_notification.default.confirm(strings.rate_note_title,rateRemoveText,strings.Ok,strings.Cancel,(function(){serviceCall("rate_note",{id:ident},(function(result){result.status&&(lastHistoryId=result.historyid,rating.html(" ".concat(result.rating," ")),2==sortby&&sortNotes(note.closest(".board_column_content"))),rating.data("disabled",!1)}))})).then((function(rateModal){rateModal.getRoot().on(_modal_events.default.hidden,(function(){rating.data("disabled",!1)}))}))}})))}}(ident)})),notecontrols.append(rateElement)}if(iseditable){var removeElement=(0,_jquery.default)('
');if(handleAction(removeElement,(()=>{!function(ident){_notification.default.confirm(strings.remove_note_title,strings.remove_note_text,strings.delete,strings.Cancel,(function(){serviceCall("delete_note",{id:ident},(function(result){if(result.status){lastHistoryId=result.historyid;let note=getNote(ident);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}}))}))}(ident)})),notecontrols.append(removeElement),1==usersCanEdit||isEditor){var moveElement=(0,_jquery.default)('
');notecontrols.append(moveElement),_movenotesdialog.default.init(ownerId,moveNote)}var editElement=(0,_jquery.default)('
');notecontrols.append(editElement),handleAction(editElement,(()=>{beginEdit()})),updateSortable(),setAttachment(note,attachment)}else previewAttachment(note,attachment);note.append(notecontrols),handleAction(notecontent,(()=>fullScreenNote(ident,notecontent))),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide());var lastOne=columnContent.find(".board_note").last();lastOne.length?note.insertAfter(lastOne):columnContent.prepend(note)}else(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_newcontent").append(note),note.hide(),beginEdit()},addColumn=function(ident,name,locked,notes,colour){let headerStyle='style="border-top: 10px solid #'.concat(colour,'"');var iseditable=isEditor,nameCache=null,column=(0,_jquery.default)('
')),columnHeader=(0,_jquery.default)('
'),columnSort=(0,_jquery.default)('
'),columnName=(0,_jquery.default)('
'+name+"
"),columnContent=(0,_jquery.default)('
'),columnNewContent=(0,_jquery.default)('
');if(3!=sortby&&columnHeader.append(columnSort),columnHeader.append(columnName),options.hideheaders&&columnName.addClass("d-none"),columnSort.on("click",(function(){sortNotes(columnContent,!0)})),iseditable){column.addClass("mod_board_editablecolumn");const lockIcon=locked?"fa-lock":"fa-unlock",lockElement=(0,_jquery.default)('
')),lockstring=locked?"aria_column_locked":"aria_column_unlocked";(0,_str.get_string)(lockstring,"mod_board",name).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)})),handleAction(lockElement,(()=>{const lockColumn="true"!==column.attr("data-locked");serviceCall("lock_column",{id:ident,status:lockColumn},(function(result){const columnName=column.find(".mod_board_column_name").text();result.status&&(lockColumn?(lockElement.removeClass("fa-unlock").addClass("fa-lock"),column.attr("data-locked","true"),column.find(".board_button.newnote").addClass("d-none"),(0,_str.get_string)("aria_column_locked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))):(lockElement.removeClass("fa-lock").addClass("fa-unlock"),column.attr("data-locked","false"),column.find(".board_button.newnote").removeClass("d-none"),(0,_str.get_string)("aria_column_unlocked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))),lastHistoryId=result.historyid,updateSortable())}))})),columnHeader.append(lockElement),columnHeader.addClass("icon-size-3");const moveElement=(0,_jquery.default)('
');columnHeader.append(moveElement),_movecolumnsdialog.default.init(moveColumn);var removeElement=(0,_jquery.default)('
');handleAction(removeElement,(()=>{_notification.default.confirm(strings.remove_column_title,(0,_str.get_string)("remove_column_text","mod_board",getColumnName(ident)),strings.delete,strings.Cancel,(function(){serviceCall("delete_column",{id:ident},(function(result){result.status&&(column.remove(),lastHistoryId=result.historyid)}))}))})),columnHeader.append(removeElement)}if(column.append(columnHeader),column.append(columnContent),column.append(columnNewContent),iseditable&&(!function(elem,callback,callBeforeOnKeyEditing){if(elem.is(":editable"))throw new Error("handleEditableAction - must be called before setting the element as editable");elem.on("dblclick keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode)||elem.is(":editing"))return;if(e.preventDefault(),callBeforeOnKeyEditing&&callback(),elem.editable("open"),callBeforeOnKeyEditing)return}callback()}))}(columnName,(function(){nameCache=columnName.html()}),!0),columnName.editable({toggleFontSize:!1,closeOnEnter:!0,callback:function(data){data.content?serviceCall("update_column",{id:ident,name:columnName.html()},(function(result){result.status?(lastHistoryId=result.historyid,updateColumnAria(ident)):(columnName.html(nameCache),nameCache=null)}),(function(){columnName.html(nameCache),nameCache=null})):(columnName.html(nameCache),nameCache=null)}})),!isReadOnlyBoard){const newNoteButton=(0,_jquery.default)('
');columnNewContent.append(newNoteButton),"true"===column.attr("data-locked")&&newNoteButton.addClass("d-none"),handleAction(columnNewContent.find(".newnote"),(function(){addNote(ident,0,null,null,null,{id:userId},0,0)}))}var lastOne=(0,_jquery.default)(".mod_board .board_column_hasdata").last();if(lastOne.length?column.insertAfter(lastOne):(0,_jquery.default)(".mod_board").append(column),notes)for(var index in notes){let sortorder=3==sortby?notes[index].sortorder:notes[index].timecreated;addNote(ident,notes[index].id,notes[index].heading,notes[index].content,{type:notes[index].type,info:notes[index].info,url:notes[index].url},{id:notes[index].userid,firstname:notes[index].firstname,lastname:notes[index].lastname},sortorder,notes[index].rating)}sortNotes(columnContent),updateColumnAria(ident),(isEditor||1==usersCanEdit)&&updateSortable(),isEditor&&columnSorting()};const getColumnName=id=>(0,_jquery.default)(".board_column[data-ident='".concat(id,"']")).find(".mod_board_column_name").html();const selectHeadingColour=()=>{let colCount=(0,_jquery.default)(".board_column").length-1,colourCount=options.colours.length;return options.colours[colCount%colourCount]};var updateNote=function(note,heading,data){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteText.html(data.content),noteHeading.html(data.heading),setAttachment(note,data.attachment),updateNoteAria(data.id),noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())},processBoardHistory=function(){serviceCall("board_history",{id:board.id,ownerid:ownerId,since:lastHistoryId},(function(boardhistory){for(var index in boardhistory){var item=boardhistory[index];if(item.boardid==board.id){var data=JSON.parse(item.content);if("add_note"==item.action){let sortorder=3==sortby?data.sortorder:data.timecreated;addNote(data.columnid,data.id,data.heading,data.content,data.attachment,{id:item.userid},sortorder,data.rating),updateNoteAria(data.id),sortNotes((0,_jquery.default)(".board_column[data-ident="+data.columnid+"] .board_column_content"))}else if("update_note"==item.action){let note=getNote(data.id),formModal=editModal,historyData=data;if(note){getNoteHeadingForNote(note);editingNote==data.id?_notification.default.confirm(strings.note_changed_title,strings.note_changed_text,strings.Ok,strings.Cancel,(function(){formModal.hide(),updateNote(note,0,historyData),stopNoteEdit()})):updateNote(note,0,data)}}else if("delete_note"==item.action){editingNote==data.id&&(_notification.default.alert(strings.warning,strings.note_deleted_text),stopNoteEdit());let note=getNote(data.id);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}else if("add_column"==item.action)addColumn(data.id,data.name,!1,{},selectHeadingColour());else if("move_column"==item.action){const board=(0,_jquery.default)(".mod_board");data.sortorder.forEach((column=>{board.find(".board_column[data-ident='".concat(column,"']")).detach().appendTo(board)}))}else if("update_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"'] .mod_board_column_name").html(data.name),updateColumnAria(data.id);else if("lock_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").attr("data-locked",data.locked),data.locked?(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").addClass("d-none"):(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").removeClass("d-none"),updateSortable();else if("delete_column"==item.action){var column=(0,_jquery.default)(".board_column[data-ident='"+data.id+"']");editingNote&&column.find('.board_note[data-ident="'+editingNote+'"]').length&&stopNoteEdit(),column.remove()}else if("rate_note"==item.action){var note=getNote(data.id);note.find(".mod_board_rating").html(data.rating),2==sortby&&sortNotes(note.closest(".board_column_content"))}lastHistoryId=item.id}}updateBoard()}))},updateBoard=function(instant){instant?processBoardHistory():options.history_refresh>0&&(reloadTimer&&stopUpdating(),reloadTimer=setTimeout(processBoardHistory,1e3*options.history_refresh))},stopUpdating=function(){clearTimeout(reloadTimer),reloadTimer=null},sortNotes=function(content,toggle){var desc,asc,sortCol=(0,_jquery.default)(content).parent().find(".mod_board_column_sort"),direction=(0,_jquery.default)(content).data("sort");if(direction||(direction=2==sortby?"desc":"asc"),toggle&&(direction="asc"==direction?"desc":"asc"),"asc"==direction?(sortCol.removeClass("fa-angle-down"),sortCol.addClass("fa-angle-up")):(sortCol.removeClass("fa-angle-up"),sortCol.addClass("fa-angle-down")),(0,_jquery.default)(content).data("sort",direction),1==sortby)desc=function(a,b){return(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(2==sortby)desc=function(a,b){return(0,_jquery.default)(b).find(".mod_board_rating").text()-(0,_jquery.default)(a).find(".mod_board_rating").text()||(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).find(".mod_board_rating").text()-(0,_jquery.default)(b).find(".mod_board_rating").text()||(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(3==sortby){let sortElements=(a,b)=>(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder");return void(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort(sortElements).appendTo((0,_jquery.default)(content))}(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort("asc"===direction?asc:desc).appendTo((0,_jquery.default)(content))},updateSortable=function(){let fromColumnID;(0,_jquery.default)(".board_column[data-locked='false'] .board_column_content").sortable({connectWith:".board_column[data-locked='false'] .board_column_content",cancel:".mod_board_nosort",handle:".move_note",start:function(_,ui){fromColumnID=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){var note=(0,_jquery.default)(ui.item),tocolumn=note.closest(".board_column"),elem=(0,_jquery.default)(this),noteid=note.data("ident"),columnid=tocolumn.data("ident");let sortorder=tocolumn.find(".board_column_content").children().index((0,_jquery.default)(".board_note[data-ident=".concat(noteid,"]")));moveNote(fromColumnID,{id:noteid,columnid:columnid,ownerid:ownerId,sortorder:sortorder},elem)}})};const moveNote=(fromColumnID,payload,elem)=>{updateSortOrders(fromColumnID,payload.columnid,payload.id,payload.sortorder),serviceCall("move_note",payload,(result=>{result.status?(lastHistoryId=result.historyid,updateNoteAria(payload.id),updateBoard(),sortNotes((0,_jquery.default)(".board_column[data-ident=".concat(payload.columnid,"] .board_column_content")))):elem&&elem.sortable("cancel")}))},columnSorting=()=>{let movingColumnId;(0,_jquery.default)(".mod_board").sortable({connectWith:".mod_board",axis:"x",containment:".mod_board_wrapper",cancel:".mod_board_nosort",handle:".mod_column_move",start:function(_,ui){movingColumnId=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){let column=(0,_jquery.default)(ui.item),sortorder=(0,_jquery.default)(".mod_board").find(".board_column").index(column);moveColumn({id:movingColumnId,sortorder:sortorder})}})},moveColumn=payload=>{serviceCall("move_column",payload,!1)},updateSortOrders=(fromColumnID,toColumnID,noteID,newSortOrder)=>{let toColumn=(0,_jquery.default)(".board_column[data-ident=".concat(toColumnID,"] .board_column_content")),movedNote=(0,_jquery.default)(".board_note[data-ident=".concat(noteID,"]")),oldSortOrder=movedNote.data("sortorder"),toChildren=toColumn.children();if(fromColumnID==toColumnID)toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");oldSortOrder=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1):oldSortOrder>newSortOrder&&sortOrder>=newSortOrder&&sortOrder<=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)}));else{let fromChildren=(0,_jquery.default)(".board_column[data-ident=".concat(fromColumnID,"] .board_column_content")).children();toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>=newSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)})),fromChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1)}))}movedNote.data("sortorder",newSortOrder)};var getBody=function(noteid,columnid,ownerId){var params={noteid:noteid,columnid:columnid,ownerid:ownerId};return _fragment.default.loadFragment("mod_board","note_form",contextid,params)},showModalForm=function(note){let title,noteId=0,columnId=note.data("column"),columnIdentifier=(0,_jquery.default)(".board_column[data-ident="+columnId+"]").find(".mod_board_column_name").text();note.data("ident")?(noteId=note.data("ident"),title=strings.modal_title_edit.replace("{column}",columnIdentifier)):title=strings.modal_title_new.replace("{column}",columnIdentifier),_modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:title,body:getBody(noteId,columnId,ownerId),large:!0,removeOnClose:!0}).then((function(modal){return modal.getBodyPromise().then((function(){let saveInProgress=!1;editModal=modal,modal.setLarge(),modal.setSaveButtonText(strings.post_button_text),modal.setButtonText("cancel",strings.cancel_button_text),modal.getRoot().on(_modal_events.default.hidden,(function(){stopNoteEdit(),note.data("ident")||note.remove()})),modal.getRoot().on(_modal_events.default.save,(function(e){e.preventDefault(),modal.getRoot().find("form").submit()}));var changeEvent=document.createEvent("HTMLEvents");if(changeEvent.initEvent("change",!0,!0),modal.getRoot().on("submit","form",(function(e){if(e.preventDefault(),saveInProgress)return;if(saveInProgress=!0,modal.getRoot().find("form").get(0).reportValidity()){modal.getRoot().find(":input").each((function(index,element){element.dispatchEvent(changeEvent)}));var invalid=_jquery.default.merge(modal.getRoot().find('[aria-invalid="true"]'),modal.getRoot().find(".error"),modal.getRoot().find(":invalid"));if(invalid.length)return invalid.first().focus(),void(saveInProgress=!1);var formData=JSON.stringify(modal.getRoot().find("form").serialize());serviceCall("submit_form",{contextid:contextid,jsonformdata:formData},(function(result){result.status?("insert"==result.action?(lastHistoryId=result.historyid,note.remove(),addNote(columnId,result.note.id,result.note.heading,result.note.content,{type:result.note.type,info:result.note.info,url:result.note.url},{id:result.note.userid},result.note.timecreated,result.note.rating),sortNotes((0,_jquery.default)(".board_column[data-ident="+columnId+"] .board_column_content")),updateNoteAria(result.note.id)):(lastHistoryId=result.historyid,getNoteTextForNote(note).html(result.note.content),getNoteHeadingForNote(note).html(result.note.heading),updateNoteAria(result.note.id),setAttachment(note,{type:result.note.type,info:result.note.info,url:result.note.url})),stopNoteEdit(),Y.use("moodle-core-formchangechecker",(function(){M.core_formchangechecker.reset_form_dirty_state()})),modal.destroy()):modal.destroy()}))}else saveInProgress=!1})),1==mediaSelection){modal.getRoot().find("#fitem_id_mediatype").hide();let mediaSelect=modal.getRoot().find("#fitem_id_mediatype select"),ytButton=modal.getRoot().find(".mod_board_attachment_button.youtube_button"),pictureButton=modal.getRoot().find(".mod_board_attachment_button.image_button"),linkButton=modal.getRoot().find(".mod_board_attachment_button.link_button"),updateMediaButtons=function(){switch(ytButton.removeClass("selected"),pictureButton.removeClass("selected"),linkButton.removeClass("selected"),mediaSelect.val()){case"1":ytButton.addClass("selected");break;case"2":pictureButton.addClass("selected");break;case"3":linkButton.addClass("selected")}};updateMediaButtons(),handleAction(ytButton,(function(){"1"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(1),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(pictureButton,(function(){"2"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(2),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(linkButton,(function(){"3"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(3),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)}))}else modal.getRoot().find("#fitem_id_mediabuttons").hide();return function(note,modal){let addYoutube,addImage,addLink,postButton,cancelButton,columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text(),modalRoot=modal.getRoot();if(note.data("ident")){var noteIdentifier=textIdentifierForNote(note);postButton=strings.aria_postedit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),cancelButton=strings.aria_canceledit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addYoutube=strings.aria_addmedia.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addImage=strings.aria_addmedia.replace("{type}",strings.option_image).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addLink=strings.aria_addmedia.replace("{type}",strings.option_link).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)}else postButton=strings.aria_postnew.replace("{column}",columnIdentifier),cancelButton=strings.aria_cancelnew.replace("{column}",columnIdentifier),addYoutube=strings.aria_addmedianew.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier),addImage=strings.aria_addmedianew.replace("{type}",strings.option_image).replace("{column}",columnIdentifier),addLink=strings.aria_addmedianew.replace("{type}",strings.option_link).replace("{column}",columnIdentifier);1==mediaSelection&&(modalRoot.find(".mod_board_attachment_button.youtube_button").attr("aria-label",addYoutube),modalRoot.find(".mod_board_attachment_button.youtube_button").attr("title",addYoutube),modalRoot.find(".mod_board_attachment_button.image_button").attr("aria-label",addImage),modalRoot.find(".mod_board_attachment_button.image_button").attr("title",addImage),modalRoot.find(".mod_board_attachment_button.link_button").attr("aria-label",addLink),modalRoot.find(".mod_board_attachment_button.link_button").attr("title",addLink));let button=modalRoot.find(modal.getActionSelector("save"));button&&button.attr("aria-label",postButton),button=modalRoot.find(modal.getActionSelector("cancel")),button&&button.attr("aria-label",cancelButton)}(note,modal),modal.show(),modal})).catch(_notification.default.exception),modal})).catch(_notification.default.exception)},fullScreenNote=(ident,notecontent)=>{const heading=getNoteHeadingForNote(notecontent).html(),modalBody=(0,_jquery.default)(document.createElement("div"));modalBody.addClass("mod_board_note_content");const text=getNoteTextForNote(notecontent);text&&modalBody.append(text.clone());const preview=(note=notecontent,(0,_jquery.default)(note).find(".mod_board_preview"));var note;preview&&modalBody.append(preview.clone());const commentArea=(0,_jquery.default)(document.createElement("div"));commentArea.attr("data-region","comment-area"),modalBody.append(commentArea),_comments.default.fetchFor(ident,commentArea),_modal_factory.default.create({type:_modal_factory.default.types.CANCEL,title:heading,body:modalBody}).then((function(modal){return modal.setLarge(),modal.show(),modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal}),this).catch(_notification.default.exception)},init=function(){serviceCall("get_board",{id:board.id,ownerid:ownerId},(function(columns){if(columns)for(var index in columns)addColumn(columns[index].id,columns[index].name,columns[index].locked,columns[index].notes||{},options.colours[columns[index].id%options.colours.length]);var column,newBusy;isEditor&&(column=(0,_jquery.default)('
'),newBusy=!1,column.append('
'),handleAction(column.find(".newcolumn"),(function(){newBusy||(newBusy=!0,serviceCall("add_column",{boardid:board.id,name:strings.default_column_heading},(function(result){addColumn(result.id,strings.default_column_heading,!1,{},selectHeadingColour()),lastHistoryId=result.historyid,newBusy=!1}),(function(){newBusy=!1})))})),(0,_jquery.default)(".mod_board").append(column)),lastHistoryId=board.historyid,isEditor&&(updateSortable(),columnSorting()),updateBoard()}))},stringsInfo=[];for(var string in strings)stringsInfo.push({key:string,component:"mod_board"});_jquery.default.when((0,_str.get_strings)(stringsInfo)).done((function(results){var index=0;for(string in strings)strings[string]=results[index++];init()}))},_jquery=_interopRequireDefault(_jquery),_ajax=_interopRequireDefault(_ajax),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_fragment=_interopRequireDefault(_fragment),_comments=_interopRequireDefault(_comments),_movenotesdialog=_interopRequireDefault(_movenotesdialog),_movecolumnsdialog=_interopRequireDefault(_movecolumnsdialog);const isAriaTriggerKey=function(key){return 13==key||32==key},encodeText=function(rawText){return(0,_jquery.default)("
").text(rawText).html()},decodeText=function(encodedText){return(0,_jquery.default)("
").html(encodedText).text()},handleAction=function(elem,callback){return elem.on("click keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode))return;e.preventDefault()}callback(),e.preventDefault()}))};return _exports.default})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=function(settings){var strings={default_column_heading:"",post_button_text:"",cancel_button_text:"",remove_note_title:"",remove_note_text:"",remove_column_title:"",note_changed_title:"",note_changed_text:"",note_deleted_text:"",rate_note_title:"",rate_note_text:"",rate_remove_note_text:"",Ok:"",delete:"",Cancel:"",warning:"",modal_title_new:"",modal_title_edit:"",option_youtube:"",option_image:"",option_link:"",aria_newcolumn:"",aria_newpost:"",aria_deletecolumn:"",aria_movecolumn:"",aria_deletepost:"",aria_movepost:"",aria_editpost:"",aria_addmedia:"",aria_addmedianew:"",aria_deleteattachment:"",aria_postedit:"",aria_canceledit:"",aria_postnew:"",aria_cancelnew:"",aria_ratepost:"",invalid_file_extension:"",invalid_file_size_min:"",invalid_file_size_max:"",invalid_youtube_url:""},options=JSON.parse(settings.settings)||{},board=options.board||{},contextid=options.contextid;var reloadTimer=null,lastHistoryId=null,isEditor=options.isEditor||!1,usersCanEdit=options.usersCanEdit,userId=parseInt(options.userId)||-1,userFullname=options.userFullname,ownerId=parseInt(options.ownerId),mediaSelection=options.mediaselection||1,editingNote=0,isReadOnlyBoard=options.readonly||!1,showauthorofnote=options.showauthorofnote||!1,allowshowauthorofnoteonboard=options.allowshowauthorofnoteonboard||!1,ratingenabled=options.ratingenabled,sortby=options.sortby||1,editModal=null,enableblanktarget=1===parseInt(options.enableblanktarget),serviceCall=function(method,args,callback,failcallback){"board_history"!==method&&stopUpdating(),function(method,args,callback,failcallback){_ajax.default.call([{methodname:"mod_board_"+method,args:args,done:function(data){callback(data)},fail:function(error){_notification.default.exception(error),failcallback&&failcallback(error)}}])}(method,args,(function(){callback&&callback.apply(null,arguments),"board_history"!==method&&"get_board"!=method&&updateBoard(!0)}),failcallback)},getNote=function(ident){return(0,_jquery.default)(".board_note[data-ident='"+ident+"']")},getNoteTextForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_text")},getNoteHeadingForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_heading")},getNoteBorderForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_border")},getNoteAttachmentsForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_attachment")},textIdentifierForNote=function(note){var noteText=getNoteTextForNote(note).html(),noteHeading=getNoteHeadingForNote(note).html(),noteAttachment=attachmentDataForNote(note);return noteHeading.length>0?noteHeading:noteText.length>0?noteText.replace(//gi," ").replace(/\n/g," ").split(/\s+/).slice(0,5).join(" "):noteAttachment.info&¬eAttachment.info.length>0?noteAttachment.info:null},updateNoteAria=function(noteId){var note=getNote(noteId),columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text();if(noteId){var noteIdentifier=textIdentifierForNote(note),deleteNoteString=strings.aria_deletepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier);note.find(".delete_note").attr("aria-label",deleteNoteString).attr("title",deleteNoteString);var moveNoteString=strings.aria_movepost.replace("{post}",noteIdentifier);note.find(".move_note").attr("aria-label",moveNoteString).attr("title",moveNoteString);var editNoteString=strings.aria_editpost.replace("{post}",noteIdentifier);note.find(".edit_note").attr("aria-label",editNoteString).attr("title",editNoteString),note.find(".mod_board_rating").attr("aria-label",strings.aria_ratepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)),note.find(".note_ariatext").html(noteIdentifier)}},updateColumnAria=function(columnId){var column=(0,_jquery.default)(".board_column[data-ident="+columnId+"]"),columnIdentifier=column.find(".mod_board_column_name").text(),newNoteString=strings.aria_newpost.replace("{column}",columnIdentifier),moveColumnString=strings.aria_movecolumn.replace("{column}",columnIdentifier),deleteColumnString=strings.aria_deletecolumn.replace("{column}",columnIdentifier);column.find(".newnote").attr("aria-label",newNoteString).attr("title",newNoteString),column.find(".mod_column_move").attr("aria-label",moveColumnString).attr("title",moveColumnString),column.find(".delete_column").attr("aria-label",deleteColumnString).attr("title",deleteColumnString),column.find(".board_note").each((function(index,note){updateNoteAria((0,_jquery.default)(note).data("ident"))}))},stopNoteEdit=function(){if(editingNote){var note=getNote(editingNote);if(note){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())}editingNote=0}else getNote(0).remove()};const sortAfterDelete=(columnID,sortorder)=>{let column=(columnID=>(0,_jquery.default)(".board_column[data-ident='".concat(columnID,"'] .board_column_content")))(columnID);column.children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so-1)}))};var setAttachment=function(note,attachment){var noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment){attachment?attachment.type+="":attachment={type:"0"};var attType=noteAttachment.find(".mod_board_type");attType.val(attachment.type?attachment.type:"0"),attType.val()>"0"&&(noteAttachment.find(".info").val(decodeText(attachment.info)),noteAttachment.find(".url").val(decodeText(attachment.url))),function(note){var noteAttachment=getNoteAttachmentsForNote(note),type=noteAttachment.find(".mod_board_type").val(),attachmentInfo=noteAttachment.find(".info"),attachmentUrl=noteAttachment.find(".url"),attachmentFile=noteAttachment.find(".mod_board_file");type>"0"?(attachmentInfo.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_info"]),attachmentUrl.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_url"]),attachmentInfo.show(),2==type&&FileReader?(attachmentFile.show(),attachmentUrl.hide()):(attachmentFile.hide(),attachmentUrl.show())):(attachmentInfo.hide(),attachmentUrl.hide(),attachmentFile.hide(),attachmentInfo.val(""),attachmentUrl.val(""))}(note)}previewAttachment(note,attachment)},attachmentDataForNote=function(note){var attachment={type:0,info:null,url:null,filename:null,filecontents:null},noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment.length){attachment.type=noteAttachment.find(".mod_board_type").val(),attachment.info=encodeText(noteAttachment.find(".info").val()),attachment.url=encodeText(noteAttachment.find(".url").val());var fileElem=noteAttachment.find(".mod_board_file>input");fileElem.data("filename")&&(attachment.filename=fileElem.data("filename"),attachment.filecontents=fileElem.data("filecontents"))}return attachment.info&&attachment.info.length||attachment.url&&attachment.url.length||attachment.filename||(attachment.type=0),attachment},attachmentTypeToString=function(type){switch(type){case"1":return"youtube";case"2":return"image";case"3":return"link";default:return null}};var previewAttachment=function(note,attachment){var elem=note.find(".mod_board_preview");if(attachment||(attachment=attachmentDataForNote(note)),getNoteTextForNote(note).html().length?elem.removeClass("mod_board_notext"):elem.addClass("mod_board_notext"),elem.removeClass("wrapper_youtube"),elem.removeClass("wrapper_image"),elem.removeClass("wrapper_url"),attachment.filename&&2==parseInt(attachment.type))elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();else if(attachment.url){const blanktarget=enableblanktarget?' target="_blank"':"";switch(parseInt(attachment.type)){case 1:{let url=(url=>{let videoID=url.match(/(\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/);return videoID&&void 0!==videoID[2]&&11===videoID[2].length?"https://www.youtube-nocookie.com/embed/".concat(videoID[2]):null})(attachment.url);null===url?elem.html(strings.invalid_youtube_url):(elem.html(''),elem.addClass("wrapper_youtube").addClass("position-relative")),elem.show()}break;case 2:elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();break;case 3:elem.html('"+(attachment.info||attachment.url)+""),elem.addClass("wrapper_url"),elem.show();break;default:elem.html(""),elem.hide()}}else elem.html(""),elem.hide()},addNote=function(columnid,ident,heading,content,attachment,owner,sortorder,rating){var ismynote=owner.id==userId||!ident,iseditable=isEditor||ismynote&&!isReadOnlyBoard;if(!ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}if(3==sortby){(0,_jquery.default)(".board_column[data-ident='".concat(columnid,"'] .board_column_content")).children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>=parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so+1)}))}var note=(0,_jquery.default)('
');ismynote&¬e.addClass("mod_board_mynote"),iseditable&¬e.addClass("mod_board_editablenote"),ismynote||iseditable||note.addClass("mod_board_nosort");var notecontent=(0,_jquery.default)('
'),notecontrols=(0,_jquery.default)('
'),noteHeading=(0,_jquery.default)('
'+(heading||"")+"
"),noteAuthorusername=(0,_jquery.default)(""),noteBorder=(0,_jquery.default)('
'),noteText=(0,_jquery.default)('
'+(content||"")+"
"),noteAriaText=(0,_jquery.default)(''),attachmentPreview=(0,_jquery.default)('
');if(1==allowshowauthorofnoteonboard&&1==showauthorofnote){let fullname="";fullname=ismynote?userFullname:owner.fullname,noteAuthorusername='
'+fullname+"
"}notecontent.append(noteHeading),notecontent.append(noteAuthorusername),notecontent.append(noteBorder),notecontent.append(noteText),notecontent.append(noteAriaText),notecontent.append(attachmentPreview),note.append(notecontent);var columnContent=(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_content"),beginEdit=()=>{!function(ident){if(editingNote){if(editingNote==ident)return;stopNoteEdit()}if(ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}var note=getNote(ident);note&&(showModalForm(note),ident&&(editingNote=ident))}(ident)};if(ident){if(ratingenabled){note.addClass("mod_board_rateablenote");var rateElement=(0,_jquery.default)('
'.concat(rating,"
"));handleAction(rateElement,(()=>{!function(ident){if(ratingenabled&&!isReadOnlyBoard){var note=getNote(ident),rating=note.find(".mod_board_rating");rating.data("disabled")||(rating.data("disabled",!0),serviceCall("can_rate_note",{id:ident},(function(result){if(result.canrate){const rateRemoveText=result.hasrated?strings.rate_remove_note_text:strings.rate_note_text;_notification.default.confirm(strings.rate_note_title,rateRemoveText,strings.Ok,strings.Cancel,(function(){serviceCall("rate_note",{id:ident},(function(result){result.status&&(lastHistoryId=result.historyid,rating.html(" ".concat(result.rating," ")),2==sortby&&sortNotes(note.closest(".board_column_content"))),rating.data("disabled",!1)}))})).then((function(rateModal){rateModal.getRoot().on(_modal_events.default.hidden,(function(){rating.data("disabled",!1)}))}))}})))}}(ident)})),notecontrols.append(rateElement)}if(iseditable){var removeElement=(0,_jquery.default)('
');if(handleAction(removeElement,(()=>{!function(ident){_notification.default.confirm(strings.remove_note_title,strings.remove_note_text,strings.delete,strings.Cancel,(function(){serviceCall("delete_note",{id:ident},(function(result){if(result.status){lastHistoryId=result.historyid;let note=getNote(ident);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}}))}))}(ident)})),notecontrols.append(removeElement),1==usersCanEdit||isEditor){var moveElement=(0,_jquery.default)('
');notecontrols.append(moveElement),_movenotesdialog.default.init(ownerId,moveNote)}var editElement=(0,_jquery.default)('
');notecontrols.append(editElement),handleAction(editElement,(()=>{beginEdit()})),updateSortable(),setAttachment(note,attachment)}else previewAttachment(note,attachment);note.append(notecontrols),handleAction(notecontent,(()=>fullScreenNote(ident,notecontent))),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide());var lastOne=columnContent.find(".board_note").last();lastOne.length?note.insertAfter(lastOne):columnContent.prepend(note)}else(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_newcontent").append(note),note.hide(),beginEdit()},addColumn=function(ident,name,locked,notes,colour){let headerStyle='style="border-top: 10px solid #'.concat(colour,'"');var iseditable=isEditor,nameCache=null,column=(0,_jquery.default)('
')),columnHeader=(0,_jquery.default)('
'),columnSort=(0,_jquery.default)('
'),columnName=(0,_jquery.default)('
'+name+"
"),columnContent=(0,_jquery.default)('
'),columnNewContent=(0,_jquery.default)('
');if(3!=sortby&&columnHeader.append(columnSort),columnHeader.append(columnName),options.hideheaders&&columnName.addClass("d-none"),columnSort.on("click",(function(){sortNotes(columnContent,!0)})),iseditable){column.addClass("mod_board_editablecolumn");const lockIcon=locked?"fa-lock":"fa-unlock",lockElement=(0,_jquery.default)('
')),lockstring=locked?"aria_column_locked":"aria_column_unlocked";(0,_str.get_string)(lockstring,"mod_board",name).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)})),handleAction(lockElement,(()=>{const lockColumn="true"!==column.attr("data-locked");serviceCall("lock_column",{id:ident,status:lockColumn},(function(result){const columnName=column.find(".mod_board_column_name").text();result.status&&(lockColumn?(lockElement.removeClass("fa-unlock").addClass("fa-lock"),column.attr("data-locked","true"),column.find(".board_button.newnote").addClass("d-none"),(0,_str.get_string)("aria_column_locked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))):(lockElement.removeClass("fa-lock").addClass("fa-unlock"),column.attr("data-locked","false"),column.find(".board_button.newnote").removeClass("d-none"),(0,_str.get_string)("aria_column_unlocked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))),lastHistoryId=result.historyid,updateSortable())}))})),columnHeader.append(lockElement),columnHeader.addClass("icon-size-3");const moveElement=(0,_jquery.default)('
');columnHeader.append(moveElement),_movecolumnsdialog.default.init(moveColumn);var removeElement=(0,_jquery.default)('
');handleAction(removeElement,(()=>{_notification.default.confirm(strings.remove_column_title,(0,_str.get_string)("remove_column_text","mod_board",getColumnName(ident)),strings.delete,strings.Cancel,(function(){serviceCall("delete_column",{id:ident},(function(result){result.status&&(column.remove(),lastHistoryId=result.historyid)}))}))})),columnHeader.append(removeElement)}if(column.append(columnHeader),column.append(columnContent),column.append(columnNewContent),iseditable&&(!function(elem,callback,callBeforeOnKeyEditing){if(elem.is(":editable"))throw new Error("handleEditableAction - must be called before setting the element as editable");elem.on("dblclick keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode)||elem.is(":editing"))return;if(e.preventDefault(),callBeforeOnKeyEditing&&callback(),elem.editable("open"),callBeforeOnKeyEditing)return}callback()}))}(columnName,(function(){nameCache=columnName.html()}),!0),columnName.editable({toggleFontSize:!1,closeOnEnter:!0,callback:function(data){data.content?serviceCall("update_column",{id:ident,name:columnName.html()},(function(result){result.status?(lastHistoryId=result.historyid,updateColumnAria(ident)):(columnName.html(nameCache),nameCache=null)}),(function(){columnName.html(nameCache),nameCache=null})):(columnName.html(nameCache),nameCache=null)}})),!isReadOnlyBoard){const newNoteButton=(0,_jquery.default)('
');columnNewContent.append(newNoteButton),"true"===column.attr("data-locked")&&newNoteButton.addClass("d-none"),handleAction(columnNewContent.find(".newnote"),(function(){addNote(ident,0,null,null,null,{id:userId},0,0)}))}var lastOne=(0,_jquery.default)(".mod_board .board_column_hasdata").last();if(lastOne.length?column.insertAfter(lastOne):(0,_jquery.default)(".mod_board").append(column),notes)for(var index in notes){let sortorder=3==sortby?notes[index].sortorder:notes[index].timecreated;addNote(ident,notes[index].id,notes[index].heading,notes[index].content,{type:notes[index].type,info:notes[index].info,url:notes[index].url},{id:notes[index].userid,fullname:notes[index].fullname},sortorder,notes[index].rating)}sortNotes(columnContent),updateColumnAria(ident),(isEditor||1==usersCanEdit)&&updateSortable(),isEditor&&columnSorting()};const getColumnName=id=>(0,_jquery.default)(".board_column[data-ident='".concat(id,"']")).find(".mod_board_column_name").html();const selectHeadingColour=()=>{let colCount=(0,_jquery.default)(".board_column").length-1,colourCount=options.colours.length;return options.colours[colCount%colourCount]};var updateNote=function(note,heading,data){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteText.html(data.content),noteHeading.html(data.heading),setAttachment(note,data.attachment),updateNoteAria(data.id),noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())},processBoardHistory=function(){serviceCall("board_history",{id:board.id,ownerid:ownerId,since:lastHistoryId},(function(boardhistory){for(var index in boardhistory){var item=boardhistory[index];if(item.boardid==board.id){var data=JSON.parse(item.content);if("add_note"==item.action){let sortorder=3==sortby?data.sortorder:data.timecreated;addNote(data.columnid,data.id,data.heading,data.content,data.attachment,{id:item.userid},sortorder,data.rating),updateNoteAria(data.id),sortNotes((0,_jquery.default)(".board_column[data-ident="+data.columnid+"] .board_column_content"))}else if("update_note"==item.action){let note=getNote(data.id),formModal=editModal,historyData=data;if(note){getNoteHeadingForNote(note);editingNote==data.id?_notification.default.confirm(strings.note_changed_title,strings.note_changed_text,strings.Ok,strings.Cancel,(function(){formModal.hide(),updateNote(note,0,historyData),stopNoteEdit()})):updateNote(note,0,data)}}else if("delete_note"==item.action){editingNote==data.id&&(_notification.default.alert(strings.warning,strings.note_deleted_text),stopNoteEdit());let note=getNote(data.id);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}else if("add_column"==item.action)addColumn(data.id,data.name,!1,{},selectHeadingColour());else if("move_column"==item.action){const board=(0,_jquery.default)(".mod_board");data.sortorder.forEach((column=>{board.find(".board_column[data-ident='".concat(column,"']")).detach().appendTo(board)}))}else if("update_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"'] .mod_board_column_name").html(data.name),updateColumnAria(data.id);else if("lock_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").attr("data-locked",data.locked),data.locked?(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").addClass("d-none"):(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").removeClass("d-none"),updateSortable();else if("delete_column"==item.action){var column=(0,_jquery.default)(".board_column[data-ident='"+data.id+"']");editingNote&&column.find('.board_note[data-ident="'+editingNote+'"]').length&&stopNoteEdit(),column.remove()}else if("rate_note"==item.action){var note=getNote(data.id);note.find(".mod_board_rating").html(data.rating),2==sortby&&sortNotes(note.closest(".board_column_content"))}lastHistoryId=item.id}}updateBoard()}))},updateBoard=function(instant){instant?processBoardHistory():options.history_refresh>0&&(reloadTimer&&stopUpdating(),reloadTimer=setTimeout(processBoardHistory,1e3*options.history_refresh))},stopUpdating=function(){clearTimeout(reloadTimer),reloadTimer=null},sortNotes=function(content,toggle){var desc,asc,sortCol=(0,_jquery.default)(content).parent().find(".mod_board_column_sort"),direction=(0,_jquery.default)(content).data("sort");if(direction||(direction=2==sortby?"desc":"asc"),toggle&&(direction="asc"==direction?"desc":"asc"),"asc"==direction?(sortCol.removeClass("fa-angle-down"),sortCol.addClass("fa-angle-up")):(sortCol.removeClass("fa-angle-up"),sortCol.addClass("fa-angle-down")),(0,_jquery.default)(content).data("sort",direction),1==sortby)desc=function(a,b){return(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(2==sortby)desc=function(a,b){return(0,_jquery.default)(b).find(".mod_board_rating").text()-(0,_jquery.default)(a).find(".mod_board_rating").text()||(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).find(".mod_board_rating").text()-(0,_jquery.default)(b).find(".mod_board_rating").text()||(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(3==sortby){let sortElements=(a,b)=>(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder");return void(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort(sortElements).appendTo((0,_jquery.default)(content))}(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort("asc"===direction?asc:desc).appendTo((0,_jquery.default)(content))},updateSortable=function(){let fromColumnID;(0,_jquery.default)(".board_column[data-locked='false'] .board_column_content").sortable({connectWith:".board_column[data-locked='false'] .board_column_content",cancel:".mod_board_nosort",handle:".move_note",start:function(_,ui){fromColumnID=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){var note=(0,_jquery.default)(ui.item),tocolumn=note.closest(".board_column"),elem=(0,_jquery.default)(this),noteid=note.data("ident"),columnid=tocolumn.data("ident");let sortorder=tocolumn.find(".board_column_content").children().index((0,_jquery.default)(".board_note[data-ident=".concat(noteid,"]")));moveNote(fromColumnID,{id:noteid,columnid:columnid,ownerid:ownerId,sortorder:sortorder},elem)}})};const moveNote=(fromColumnID,payload,elem)=>{updateSortOrders(fromColumnID,payload.columnid,payload.id,payload.sortorder),serviceCall("move_note",payload,(result=>{result.status?(lastHistoryId=result.historyid,updateNoteAria(payload.id),updateBoard(),sortNotes((0,_jquery.default)(".board_column[data-ident=".concat(payload.columnid,"] .board_column_content")))):elem&&elem.sortable("cancel")}))},columnSorting=()=>{let movingColumnId;(0,_jquery.default)(".mod_board").sortable({connectWith:".mod_board",axis:"x",containment:".mod_board_wrapper",cancel:".mod_board_nosort",handle:".mod_column_move",start:function(_,ui){movingColumnId=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){let column=(0,_jquery.default)(ui.item),sortorder=(0,_jquery.default)(".mod_board").find(".board_column").index(column);moveColumn({id:movingColumnId,sortorder:sortorder})}})},moveColumn=payload=>{serviceCall("move_column",payload,!1)},updateSortOrders=(fromColumnID,toColumnID,noteID,newSortOrder)=>{let toColumn=(0,_jquery.default)(".board_column[data-ident=".concat(toColumnID,"] .board_column_content")),movedNote=(0,_jquery.default)(".board_note[data-ident=".concat(noteID,"]")),oldSortOrder=movedNote.data("sortorder"),toChildren=toColumn.children();if(fromColumnID==toColumnID)toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");oldSortOrder=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1):oldSortOrder>newSortOrder&&sortOrder>=newSortOrder&&sortOrder<=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)}));else{let fromChildren=(0,_jquery.default)(".board_column[data-ident=".concat(fromColumnID,"] .board_column_content")).children();toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>=newSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)})),fromChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1)}))}movedNote.data("sortorder",newSortOrder)};var getBody=function(noteid,columnid,ownerId){var params={noteid:noteid,columnid:columnid,ownerid:ownerId};return _fragment.default.loadFragment("mod_board","note_form",contextid,params)},showModalForm=function(note){let title,noteId=0,columnId=note.data("column"),columnIdentifier=(0,_jquery.default)(".board_column[data-ident="+columnId+"]").find(".mod_board_column_name").text();note.data("ident")?(noteId=note.data("ident"),title=strings.modal_title_edit.replace("{column}",columnIdentifier)):title=strings.modal_title_new.replace("{column}",columnIdentifier),_modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:title,body:getBody(noteId,columnId,ownerId),large:!0,removeOnClose:!0}).then((function(modal){return modal.getBodyPromise().then((function(){let saveInProgress=!1;editModal=modal,modal.setLarge(),modal.setSaveButtonText(strings.post_button_text),modal.setButtonText("cancel",strings.cancel_button_text),modal.getRoot().on(_modal_events.default.hidden,(function(){stopNoteEdit(),note.data("ident")||note.remove()})),modal.getRoot().on(_modal_events.default.save,(function(e){e.preventDefault(),modal.getRoot().find("form").submit()}));var changeEvent=document.createEvent("HTMLEvents");if(changeEvent.initEvent("change",!0,!0),modal.getRoot().on("submit","form",(function(e){if(e.preventDefault(),saveInProgress)return;if(saveInProgress=!0,modal.getRoot().find("form").get(0).reportValidity()){modal.getRoot().find(":input").each((function(index,element){element.dispatchEvent(changeEvent)}));var invalid=_jquery.default.merge(modal.getRoot().find('[aria-invalid="true"]'),modal.getRoot().find(".error"),modal.getRoot().find(":invalid"));if(invalid.length)return invalid.first().focus(),void(saveInProgress=!1);var formData=JSON.stringify(modal.getRoot().find("form").serialize());serviceCall("submit_form",{contextid:contextid,jsonformdata:formData},(function(result){result.status?("insert"==result.action?(lastHistoryId=result.historyid,note.remove(),addNote(columnId,result.note.id,result.note.heading,result.note.content,{type:result.note.type,info:result.note.info,url:result.note.url},{id:result.note.userid},result.note.timecreated,result.note.rating),sortNotes((0,_jquery.default)(".board_column[data-ident="+columnId+"] .board_column_content")),updateNoteAria(result.note.id)):(lastHistoryId=result.historyid,getNoteTextForNote(note).html(result.note.content),getNoteHeadingForNote(note).html(result.note.heading),updateNoteAria(result.note.id),setAttachment(note,{type:result.note.type,info:result.note.info,url:result.note.url})),stopNoteEdit(),Y.use("moodle-core-formchangechecker",(function(){M.core_formchangechecker.reset_form_dirty_state()})),modal.destroy()):modal.destroy()}))}else saveInProgress=!1})),1==mediaSelection){modal.getRoot().find("#fitem_id_mediatype").hide();let mediaSelect=modal.getRoot().find("#fitem_id_mediatype select"),ytButton=modal.getRoot().find(".mod_board_attachment_button.youtube_button"),pictureButton=modal.getRoot().find(".mod_board_attachment_button.image_button"),linkButton=modal.getRoot().find(".mod_board_attachment_button.link_button"),updateMediaButtons=function(){switch(ytButton.removeClass("selected"),pictureButton.removeClass("selected"),linkButton.removeClass("selected"),mediaSelect.val()){case"1":ytButton.addClass("selected");break;case"2":pictureButton.addClass("selected");break;case"3":linkButton.addClass("selected")}};updateMediaButtons(),handleAction(ytButton,(function(){"1"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(1),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(pictureButton,(function(){"2"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(2),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(linkButton,(function(){"3"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(3),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)}))}else modal.getRoot().find("#fitem_id_mediabuttons").hide();return function(note,modal){let addYoutube,addImage,addLink,postButton,cancelButton,columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text(),modalRoot=modal.getRoot();if(note.data("ident")){var noteIdentifier=textIdentifierForNote(note);postButton=strings.aria_postedit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),cancelButton=strings.aria_canceledit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addYoutube=strings.aria_addmedia.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addImage=strings.aria_addmedia.replace("{type}",strings.option_image).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addLink=strings.aria_addmedia.replace("{type}",strings.option_link).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)}else postButton=strings.aria_postnew.replace("{column}",columnIdentifier),cancelButton=strings.aria_cancelnew.replace("{column}",columnIdentifier),addYoutube=strings.aria_addmedianew.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier),addImage=strings.aria_addmedianew.replace("{type}",strings.option_image).replace("{column}",columnIdentifier),addLink=strings.aria_addmedianew.replace("{type}",strings.option_link).replace("{column}",columnIdentifier);1==mediaSelection&&(modalRoot.find(".mod_board_attachment_button.youtube_button").attr("aria-label",addYoutube),modalRoot.find(".mod_board_attachment_button.youtube_button").attr("title",addYoutube),modalRoot.find(".mod_board_attachment_button.image_button").attr("aria-label",addImage),modalRoot.find(".mod_board_attachment_button.image_button").attr("title",addImage),modalRoot.find(".mod_board_attachment_button.link_button").attr("aria-label",addLink),modalRoot.find(".mod_board_attachment_button.link_button").attr("title",addLink));let button=modalRoot.find(modal.getActionSelector("save"));button&&button.attr("aria-label",postButton),button=modalRoot.find(modal.getActionSelector("cancel")),button&&button.attr("aria-label",cancelButton)}(note,modal),modal.show(),modal})).catch(_notification.default.exception),modal})).catch(_notification.default.exception)},fullScreenNote=(ident,notecontent)=>{const heading=getNoteHeadingForNote(notecontent).html(),modalBody=(0,_jquery.default)(document.createElement("div"));modalBody.addClass("mod_board_note_content");const text=getNoteTextForNote(notecontent);text&&modalBody.append(text.clone());const preview=(note=notecontent,(0,_jquery.default)(note).find(".mod_board_preview"));var note;preview&&modalBody.append(preview.clone());const commentArea=(0,_jquery.default)(document.createElement("div"));commentArea.attr("data-region","comment-area"),modalBody.append(commentArea),_comments.default.fetchFor(ident,commentArea),_modal_factory.default.create({type:_modal_factory.default.types.CANCEL,title:heading,body:modalBody}).then((function(modal){return modal.setLarge(),modal.show(),modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal}),this).catch(_notification.default.exception)},init=function(){serviceCall("get_board",{id:board.id,ownerid:ownerId},(function(columns){if(columns)for(var index in columns)addColumn(columns[index].id,columns[index].name,columns[index].locked,columns[index].notes||{},options.colours[columns[index].id%options.colours.length]);var column,newBusy;isEditor&&(column=(0,_jquery.default)('
'),newBusy=!1,column.append('
'),handleAction(column.find(".newcolumn"),(function(){newBusy||(newBusy=!0,serviceCall("add_column",{boardid:board.id,name:strings.default_column_heading},(function(result){addColumn(result.id,strings.default_column_heading,!1,{},selectHeadingColour()),lastHistoryId=result.historyid,newBusy=!1}),(function(){newBusy=!1})))})),(0,_jquery.default)(".mod_board").append(column)),lastHistoryId=board.historyid,isEditor&&(updateSortable(),columnSorting()),updateBoard()}))},stringsInfo=[];for(var string in strings)stringsInfo.push({key:string,component:"mod_board"});_jquery.default.when((0,_str.get_strings)(stringsInfo)).done((function(results){var index=0;for(string in strings)strings[string]=results[index++];init()}))},_jquery=_interopRequireDefault(_jquery),_ajax=_interopRequireDefault(_ajax),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_fragment=_interopRequireDefault(_fragment),_comments=_interopRequireDefault(_comments),_movenotesdialog=_interopRequireDefault(_movenotesdialog),_movecolumnsdialog=_interopRequireDefault(_movecolumnsdialog);const isAriaTriggerKey=function(key){return 13==key||32==key},encodeText=function(rawText){return(0,_jquery.default)("
").text(rawText).html()},decodeText=function(encodedText){return(0,_jquery.default)("
").html(encodedText).text()},handleAction=function(elem,callback){return elem.on("click keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode))return;e.preventDefault()}callback(),e.preventDefault()}))};return _exports.default})); //# sourceMappingURL=board.min.js.map \ No newline at end of file diff --git a/amd/build/board.min.js.map b/amd/build/board.min.js.map index 5ae6b4c..c7ad6b3 100755 --- a/amd/build/board.min.js.map +++ b/amd/build/board.min.js.map @@ -1 +1 @@ -{"version":3,"file":"board.min.js","sources":["../src/board.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle the board.\n *\n * @author Karen Holland \n * @copyrigt 2021 Brickfield Education Labs \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from \"jquery\";\nimport {get_strings as getStrings, get_string as getString} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport ModalFactory from \"core/modal_factory\";\nimport ModalEvents from \"core/modal_events\";\nimport Notification from \"core/notification\";\nimport \"mod_board/jquery.editable.amd\";\nimport \"mod_board/jquery.sortable.amd\";\nimport Fragment from \"core/fragment\";\nimport Comments from \"mod_board/comments\";\nimport moveNotesDialog from \"./movenotesdialog\";\nimport moveColumnsDialog from \"./movecolumnsdialog\";\n\n/**\n * Execute a ajax call to a mod_board ajax service.\n *\n * @param {string} method\n * @param {array} args\n * @param {method} callback\n * @param {method} failcallback\n * @private\n */\nconst _serviceCall = function(method, args, callback, failcallback) {\n Ajax.call([{\n methodname: 'mod_board_' + method,\n args: args,\n done: function(data) {\n callback(data);\n },\n fail: function(error) {\n Notification.exception(error);\n if (failcallback) {\n failcallback(error);\n }\n }\n }]);\n};\n\n/**\n * Indicates if this is a keycode we want to listend to for\n * aria purposes.\n *\n * @returns {boolean}\n * @param {number} key\n */\nconst isAriaTriggerKey = function(key) {\n return key == 13 || key == 32;\n};\n\n/**\n * Encodes text into html entities.\n *\n * @param {string} rawText\n * @returns {*|jQuery}\n */\nconst encodeText = function(rawText) {\n return $('
').text(rawText).html();\n};\n\n/**\n * Decodes text from html entities.\n *\n * @param {string} encodedText\n * @returns {*|jQuery}\n */\nconst decodeText = function(encodedText) {\n return $('
').html(encodedText).text();\n};\n\n/**\n * Handler for keypress and click actions.\n *\n * @param {object} elem\n * @param {function} callback\n * @returns {*}\n */\nconst handleAction = function(elem, callback) {\n return elem.on('click keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode)) {\n e.preventDefault();\n } else {\n return;\n }\n }\n\n callback();\n e.preventDefault();\n });\n};\n\n/**\n * Setting up element edibility.\n *\n * @param {object} elem\n * @param {function} callback\n * @param {function} callBeforeOnKeyEditing\n * @returns {*}\n */\nconst handleEditableAction = function(elem, callback, callBeforeOnKeyEditing) {\n if (elem.is(':editable')) {\n throw new Error('handleEditableAction - must be called before setting the element as editable');\n }\n\n // Can't use on(edit) here because we want to do actions (save cache) before the control goes into edit mode\n return elem.on('dblclick keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode) && !elem.is(':editing')) {\n e.preventDefault();\n if (callBeforeOnKeyEditing) {\n callback();\n }\n elem.editable('open');\n if (callBeforeOnKeyEditing) {\n return;\n }\n } else {\n return;\n }\n }\n\n callback();\n });\n};\n\n/**\n * The default function of the module, which does the setup of the page.\n *\n * @param {object} settings\n */\nexport default function(settings) {\n // An array of strings to load as a batch later.\n // Not necessary, but used to load all the strings in one ajax call.\n var strings = {\n default_column_heading: '',\n post_button_text: '',\n cancel_button_text: '',\n remove_note_title: '',\n remove_note_text: '',\n remove_column_title: '',\n note_changed_title: '',\n note_changed_text: '',\n note_deleted_text: '',\n rate_note_title: '',\n rate_note_text: '',\n rate_remove_note_text: '',\n Ok: '',\n delete: '',\n Cancel: '',\n warning: '',\n modal_title_new: '',\n modal_title_edit: '',\n option_youtube: '',\n option_image: '',\n option_link: '',\n\n aria_newcolumn: '',\n aria_newpost: '',\n aria_deletecolumn: '',\n aria_movecolumn: '',\n aria_deletepost: '',\n aria_movepost: '',\n aria_editpost: '',\n aria_addmedia: '',\n aria_addmedianew: '',\n aria_deleteattachment: '',\n aria_postedit: '',\n aria_canceledit: '',\n aria_postnew: '',\n aria_cancelnew: '',\n aria_ratepost: '',\n\n invalid_file_extension: '',\n invalid_file_size_min: '',\n invalid_file_size_max: '',\n\n invalid_youtube_url: '',\n };\n\n // Json decode the strings from the settings.\n var options = JSON.parse(settings.settings) || {};\n var board = options.board || {};\n var contextid = options.contextid;\n\n const MEDIA_SELECTION_BUTTONS = 1,\n ATTACHMENT_VIDEO = 1,\n ATTACHMENT_IMAGE = 2,\n ATTACHMENT_LINK = 3,\n SORTBY_DATE = 1,\n SORTBY_RATING = 2,\n SORTBY_NONE = 3;\n\n var reloadTimer = null,\n lastHistoryId = null,\n isEditor = options.isEditor || false,\n usersCanEdit = options.usersCanEdit,\n userId = parseInt(options.userId) || -1,\n userFirstname = options.firstname,\n userLastname = options.lastname,\n ownerId = parseInt(options.ownerId),\n mediaSelection = options.mediaselection || MEDIA_SELECTION_BUTTONS,\n editingNote = 0,\n isReadOnlyBoard = options.readonly || false,\n showauthorofnote = options.showauthorofnote || false,\n ratingenabled = options.ratingenabled,\n sortby = options.sortby || SORTBY_DATE,\n editModal = null,\n enableblanktarget = (parseInt(options.enableblanktarget) === 1);\n\n /**\n * Helper method to make calls to mod_board external services.\n *\n * @param {string} method\n * @param {array} args\n * @param {function} callback\n * @param {function} failcallback\n */\n var serviceCall = function(method, args, callback, failcallback) {\n if (method !== 'board_history') {\n stopUpdating();\n }\n _serviceCall(method, args, function() {\n if (callback) {\n callback.apply(null, arguments);\n }\n if (method !== 'board_history' && method != 'get_board') {\n updateBoard(true);\n }\n }, failcallback);\n };\n\n /**\n * Returns the jquery element of a given note identifier.\n *\n * @param {number} ident\n * @returns {jQuery}\n */\n var getNote = function(ident) {\n return $(\".board_note[data-ident='\" + ident + \"']\");\n };\n\n /**\n * Returns the jquery element of the note text for the given note element.\n *\n * @method getNoteTextForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteTextForNote = function(note) {\n return $(note).find(\".mod_board_note_text\");\n };\n\n /**\n * Returns the jquery element of the preview for the given note element.\n *\n * @method getNotePreviewForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNotePreviewForNote = (note) => {\n return $(note).find(\".mod_board_preview\");\n };\n\n\n /**\n * Returns the jquery element of the note heading for the given note element.\n *\n * @method getNoteHeadingForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteHeadingForNote = function(note) {\n return $(note).find(\".mod_board_note_heading\");\n };\n\n /**\n * Returns the jquery element of the note border for the given note element.\n *\n * @method getNoteBorderForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteBorderForNote = function(note) {\n return $(note).find(\".mod_board_note_border\");\n };\n\n /**\n * Gets a jquery node for the attachments of a given note.\n *\n * @method getNoteAttachmentsForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteAttachmentsForNote = function(note) {\n return $(note).find(\".mod_board_note_attachment\");\n };\n\n /**\n * Creates text identifier for a given node.\n *\n * @method textIdentifierForNote\n * @param {object} note\n * @returns {null|*|jQuery}\n */\n var textIdentifierForNote = function(note) {\n var noteText = getNoteTextForNote(note).html(),\n noteHeading = getNoteHeadingForNote(note).html(),\n noteAttachment = attachmentDataForNote(note);\n\n if (noteHeading.length > 0) {\n return noteHeading;\n }\n if (noteText.length > 0) {\n return noteText.replace(//gi, \" \").replace(/\\n/g, \" \").split(/\\s+/).slice(0, 5).join(\" \");\n }\n if (noteAttachment.info && noteAttachment.info.length > 0) {\n return noteAttachment.info;\n }\n return null;\n };\n\n /**\n * Update the Aria info for a given note id.\n *\n * @method updateNoteAria\n * @param {number} noteId\n */\n var updateNoteAria = function(noteId) {\n var note = getNote(noteId),\n columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text();\n\n if (noteId) { // New post\n var noteIdentifier = textIdentifierForNote(note),\n deleteNoteString = strings.aria_deletepost.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n\n note.find('.delete_note').attr('aria-label', deleteNoteString).attr('title', deleteNoteString);\n\n var moveNoteString = strings.aria_movepost.replace('{post}', noteIdentifier);\n note.find('.move_note').attr('aria-label', moveNoteString).attr('title', moveNoteString);\n\n var editNoteString = strings.aria_editpost.replace('{post}', noteIdentifier);\n note.find('.edit_note').attr('aria-label', editNoteString).attr('title', editNoteString);\n\n note.find('.mod_board_rating').attr('aria-label', strings.aria_ratepost.replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier));\n note.find('.note_ariatext').html(noteIdentifier);\n }\n\n };\n\n /**\n * Update the Aria information for a given column id.\n *\n * @method updateColumnAria\n * @param {number} columnId\n */\n var updateColumnAria = function(columnId) {\n var column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n newNoteString = strings.aria_newpost.replace('{column}', columnIdentifier),\n moveColumnString = strings.aria_movecolumn.replace('{column}', columnIdentifier),\n deleteColumnString = strings.aria_deletecolumn.replace('{column}', columnIdentifier);\n column.find('.newnote').attr('aria-label', newNoteString).attr('title', newNoteString);\n column.find('.mod_column_move').attr('aria-label', moveColumnString).attr('title', moveColumnString);\n column.find('.delete_column').attr('aria-label', deleteColumnString).attr('title', deleteColumnString);\n\n column.find(\".board_note\").each(function(index, note) {\n updateNoteAria($(note).data('ident'));\n });\n };\n\n /**\n * Stop the current note editing process.\n *\n * @method stopNoteEdit\n */\n var stopNoteEdit = function() {\n if (!editingNote) {\n getNote(0).remove();\n return;\n }\n\n var note = getNote(editingNote);\n\n if (note) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n }\n\n editingNote = 0;\n };\n\n /**\n * Start the editing of a particular note, by identifier.\n *\n * @method startNoteEdit\n * @param {number} ident\n */\n var startNoteEdit = function(ident) {\n\n if (editingNote) {\n if (editingNote == ident) {\n return;\n }\n stopNoteEdit();\n }\n\n if (ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n var note = getNote(ident);\n if (note) {\n showModalForm(note);\n\n if (ident) {\n editingNote = ident;\n }\n }\n };\n\n /**\n * Delete a given note, by identifier.\n *\n * @method deleteNote\n * @param {number} ident\n */\n var deleteNote = function(ident) {\n Notification.confirm(\n strings.remove_note_title, // Are you sure?\n strings.remove_note_text, // This will effect others.\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_note', { id: ident }, function (result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n let note = getNote(ident);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n }\n });\n }\n );\n };\n\n /**\n * This function gets a board column as a jQuery element.\n * @param {number} columnID The column ID.\n * @returns {jQuery}\n */\n const getColumn = (columnID) => {\n return $(`.board_column[data-ident='${columnID}'] .board_column_content`);\n };\n\n const sortAfterDelete = (columnID, sortorder) => {\n let column = getColumn(columnID);\n let elements = column.children().filter((_, element) => {\n return parseInt($(element).data('sortorder')) > parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so - 1);\n });\n };\n\n /**\n * Rate (star) a give note, by identifier.\n *\n * @method rateNote\n * @param {number} ident\n */\n var rateNote = function(ident) {\n if (!ratingenabled) {\n return;\n }\n if (isReadOnlyBoard) {\n return;\n }\n\n var note = getNote(ident),\n rating = note.find('.mod_board_rating');\n if (rating.data('disabled')) {\n return;\n }\n rating.data('disabled', true);\n\n serviceCall('can_rate_note', {id: ident}, function(result) {\n if (result.canrate) {\n const rateRemoveText = result.hasrated ? strings.rate_remove_note_text : strings.rate_note_text;\n Notification.confirm(\n strings.rate_note_title,\n rateRemoveText, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n serviceCall('rate_note', {id: ident}, function(result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n rating.html(` ${result.rating} `);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n rating.data('disabled', false);\n });\n }\n ).then(function(rateModal) {\n // Do this here, because it catches both cancel clicks, or someone clicking the X.\n rateModal.getRoot().on(ModalEvents.hidden, function() {\n rating.data('disabled', false);\n });\n });\n }\n });\n };\n\n /**\n * Update the attachment information of a note.\n *\n * @method attachmentTypeChanged\n * @param {object} note\n */\n var attachmentTypeChanged = function(note) {\n var noteAttachment = getNoteAttachmentsForNote(note),\n type = noteAttachment.find('.mod_board_type').val(),\n attachmentInfo = noteAttachment.find('.info'),\n attachmentUrl = noteAttachment.find('.url'),\n attachmentFile = noteAttachment.find('.mod_board_file');\n\n if (type > \"0\") {\n attachmentInfo.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_info']);\n attachmentUrl.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_url']);\n\n attachmentInfo.show();\n if (type == ATTACHMENT_IMAGE && FileReader) {\n attachmentFile.show();\n attachmentUrl.hide();\n } else {\n attachmentFile.hide();\n attachmentUrl.show();\n }\n } else {\n attachmentInfo.hide();\n attachmentUrl.hide();\n attachmentFile.hide();\n\n attachmentInfo.val('');\n attachmentUrl.val('');\n\n }\n };\n\n /**\n * Set the attachment of a note.\n *\n * @method setAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var setAttachment = function(note, attachment) {\n var noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment) {\n if (!attachment) {\n attachment = {type: \"0\"};\n } else {\n attachment.type += \"\";// Just in case\n }\n var attType = noteAttachment.find('.mod_board_type');\n attType.val(attachment.type ? attachment.type : \"0\");\n if (attType.val() > \"0\") {\n noteAttachment.find('.info').val(decodeText(attachment.info));\n noteAttachment.find('.url').val(decodeText(attachment.url));\n }\n attachmentTypeChanged(note, attachment);\n }\n previewAttachment(note, attachment);\n };\n\n /**\n * Returns an object with various information about a note's attachment.\n *\n * @method attachmentDataForNote\n * @param {object} note\n * @returns {{filename: null, filecontents: null, type: number, url: null, info: null}}\n */\n var attachmentDataForNote = function(note) {\n var attachment = {type: 0, info: null, url: null, filename: null, filecontents: null},\n noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment.length) {\n attachment.type = noteAttachment.find('.mod_board_type').val();\n attachment.info = encodeText(noteAttachment.find('.info').val());\n attachment.url = encodeText(noteAttachment.find('.url').val());\n var fileElem = noteAttachment.find('.mod_board_file>input');\n if (fileElem.data('filename')) {\n attachment.filename = fileElem.data('filename');\n attachment.filecontents = fileElem.data('filecontents');\n }\n }\n if ((!attachment.info || !attachment.info.length) && (!attachment.url || !attachment.url.length) &&\n (!attachment.filename)) {\n attachment.type = 0;\n }\n\n return attachment;\n };\n\n /**\n * Get the string type of a attachment type number.\n *\n * @method attachmentTypeToString\n * @param {number} type\n * @returns {string|null}\n */\n var attachmentTypeToString = function(type) {\n switch (type) {\n case \"1\": return 'youtube';\n case \"2\": return 'image';\n case \"3\": return 'link';\n default: return null;\n }\n };\n\n /**\n * This parses a youtube video ID from a URL. We can use this ID to\n * construct the embed URL.\n * @param {string} url The URL entered to the modal.\n * @returns {string | null} The youtube embed URL or null.\n */\n const getEmbedUrl = (url) => {\n // Thanks for the regex from: https://gist.github.com/rodrigoborgesdeoliveira/987683cfbfcc8d800192da1e73adc486.\n let regex = /(\\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/;\n let videoID = url.match(regex);\n if (!videoID || videoID[2] === undefined || videoID[2].length !== 11) {\n return null;\n }\n return `https://www.youtube-nocookie.com/embed/${videoID[2]}`;\n };\n\n /**\n * Display the attachment preview for a note.\n *\n * @method previewAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var previewAttachment = function(note, attachment) {\n var elem = note.find('.mod_board_preview');\n if (!attachment) {\n attachment = attachmentDataForNote(note);\n }\n\n if (!getNoteTextForNote(note).html().length) {\n elem.addClass('mod_board_notext');\n } else {\n elem.removeClass('mod_board_notext');\n }\n\n elem.removeClass('wrapper_youtube');\n elem.removeClass('wrapper_image');\n elem.removeClass('wrapper_url');\n if (attachment.filename && parseInt(attachment.type) == ATTACHMENT_IMAGE) { // Before uploading\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n } else if (attachment.url) {\n const blanktarget = enableblanktarget ? ' target=\"_blank\"' : '';\n switch (parseInt(attachment.type)) {\n case ATTACHMENT_VIDEO: { // Youtube\n let url = getEmbedUrl(attachment.url);\n if (url === null) {\n elem.html(strings.invalid_youtube_url);\n } else {\n elem.html('');\n elem.addClass('wrapper_youtube').addClass('position-relative');\n }\n elem.show();\n }\n break;\n case ATTACHMENT_IMAGE: // Image\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n break;\n case ATTACHMENT_LINK: // Url\n elem.html('' +\n (attachment.info || attachment.url) + '');\n elem.addClass('wrapper_url');\n elem.show();\n break;\n default:\n elem.html('');\n elem.hide();\n }\n } else {\n elem.html('');\n elem.hide();\n }\n };\n\n /**\n * Add a new note with the given information.\n *\n * @method addNote\n * @param {number} columnid\n * @param {number} ident\n * @param {string} heading\n * @param {string} content\n * @param {object} attachment\n * @param {object} owner\n * @param {number} sortorder\n * @param {string} rating\n */\n var addNote = function(columnid, ident, heading, content, attachment, owner, sortorder, rating) {\n var ismynote = owner.id == userId || !ident;\n var iseditable = isEditor || (ismynote && !isReadOnlyBoard);\n\n if (!ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n // Making space for this note if necessary in the sort order.\n if (sortby == SORTBY_NONE) {\n let children = $(`.board_column[data-ident='${columnid}'] .board_column_content`).children();\n let elements = children.filter((_, element) => {\n return parseInt($(element).data('sortorder')) >= parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so + 1);\n });\n }\n\n var note = $('
');\n if (ismynote) {\n note.addClass('mod_board_mynote');\n }\n if (iseditable) {\n note.addClass('mod_board_editablenote');\n }\n if (!ismynote && !iseditable) {\n note.addClass('mod_board_nosort');\n }\n\n var notecontent = $('
'),\n notecontrols = $('
'),\n noteHeading = $('
' + (heading ? heading : '') + '
'),\n noteAuthorusername = $(''),\n noteBorder = $('
'),\n noteText = $('
' + (content ? content : '') + '
'),\n noteAriaText = $('
'),\n attachmentPreview = $('
');\n\n if (showauthorofnote) {\n let firstname = '';\n let lastname = '';\n if (ismynote) {\n // Use the Name of the user itself. We do not need to get this information from somewhere else.\n firstname = userFirstname;\n lastname = userLastname;\n } else {\n firstname = owner.firstname;\n lastname = owner.lastname;\n }\n\n noteAuthorusername = '
' +\n ' ' +\n '' +\n firstname +\n '' +\n '' +\n lastname +\n '' +\n '
' ;\n }\n\n notecontent.append(noteHeading);\n notecontent.append(noteAuthorusername);\n notecontent.append(noteBorder);\n notecontent.append(noteText);\n notecontent.append(noteAriaText);\n\n notecontent.append(attachmentPreview);\n note.append(notecontent);\n\n var columnContent = $('.board_column[data-ident=' + columnid + '] .board_column_content');\n\n var beginEdit = () => {\n startNoteEdit(ident);\n };\n\n if (ident) {\n if (ratingenabled) {\n note.addClass('mod_board_rateablenote');\n var rateElement = $(`
${rating}
`);\n\n handleAction(rateElement, () => {\n rateNote(ident);\n });\n notecontrols.append(rateElement);\n }\n\n if (iseditable) {\n var removeElement = $('
');\n handleAction(removeElement, () => {\n deleteNote(ident);\n });\n\n notecontrols.append(removeElement);\n\n if (usersCanEdit == 1 || isEditor) {\n var moveElement = $('
');\n notecontrols.append(moveElement);\n moveNotesDialog.init(ownerId, moveNote);\n }\n\n var editElement = $('
');\n notecontrols.append(editElement);\n handleAction(editElement, () => {\n beginEdit();\n });\n updateSortable();\n setAttachment(note, attachment);\n } else {\n previewAttachment(note, attachment);\n }\n\n note.append(notecontrols);\n\n handleAction(notecontent, () => fullScreenNote(ident, notecontent));\n\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n\n var lastOne = columnContent.find(\".board_note\").last();\n\n if (lastOne.length) {\n note.insertAfter(lastOne);\n } else {\n columnContent.prepend(note);\n }\n } else {\n $('.board_column[data-ident=' + columnid + '] .board_column_newcontent').append(note);\n // This is effectively a note placeholder. So we don't need to show it.\n note.hide();\n beginEdit();\n }\n };\n\n /**\n * Add a new column.\n *\n * @method addColumn\n * @param {object} ident\n * @param {string} name\n * @param {bool} locked\n * @param {array} notes\n * @param {string} colour\n */\n var addColumn = function(ident, name, locked, notes, colour) {\n let headerStyle = `style=\"border-top: 10px solid #${colour}\"`;\n var iseditable = isEditor,\n nameCache = null,\n column = $(`
`),\n columnHeader = $('
'),\n columnSort = $('
'),\n columnName = $('
' + name + '
'),\n columnContent = $('
'),\n columnNewContent = $('
');\n // Only add the sort button if it makes sense.\n if (sortby != SORTBY_NONE) {\n columnHeader.append(columnSort);\n }\n columnHeader.append(columnName);\n\n if (options.hideheaders) {\n columnName.addClass('d-none');\n }\n\n columnSort.on('click', function() {\n sortNotes(columnContent, true);\n });\n\n if (iseditable) {\n column.addClass('mod_board_editablecolumn');\n const lockIcon = locked ? 'fa-lock' : 'fa-unlock';\n const lockElement = $(`
`);\n const lockstring = locked ? 'aria_column_locked' : 'aria_column_unlocked';\n getString(lockstring, 'mod_board', name).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n\n handleAction(lockElement, () => {\n const lockColumn = column.attr('data-locked') !== 'true';\n serviceCall('lock_column', {id: ident, status: lockColumn}, function(result) {\n const columnName = column.find('.mod_board_column_name').text();\n if (result.status) {\n if (lockColumn) {\n lockElement.removeClass('fa-unlock').addClass('fa-lock');\n column.attr('data-locked', 'true');\n column.find('.board_button.newnote').addClass('d-none');\n getString('aria_column_locked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n } else {\n lockElement.removeClass('fa-lock').addClass('fa-unlock');\n column.attr('data-locked', 'false');\n column.find('.board_button.newnote').removeClass('d-none');\n getString('aria_column_unlocked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n }\n lastHistoryId = result.historyid;\n updateSortable();\n }\n });\n });\n columnHeader.append(lockElement);\n\n columnHeader.addClass('icon-size-3');\n const moveElement = $('
');\n columnHeader.append(moveElement);\n moveColumnsDialog.init(moveColumn);\n var removeElement = $('
');\n handleAction(removeElement, () => {\n Notification.confirm(\n strings.remove_column_title, // Are you sure?\n getString('remove_column_text', 'mod_board', getColumnName(ident)),\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_column', {id: ident}, function(result) {\n if (result.status) {\n column.remove();\n lastHistoryId = result.historyid;\n }\n });\n }\n );\n });\n\n columnHeader.append(removeElement);\n }\n\n column.append(columnHeader);\n column.append(columnContent);\n column.append(columnNewContent);\n\n if (iseditable) {\n handleEditableAction(columnName, function() {\n nameCache = columnName.html();\n }, true);\n\n columnName.editable({\n toggleFontSize: false,\n closeOnEnter: true,\n callback: function(data) {\n if (data.content) {\n serviceCall('update_column', {id: ident, name: columnName.html()}, function(result) {\n if (!result.status) {\n columnName.html(nameCache);\n nameCache = null;\n } else {\n lastHistoryId = result.historyid;\n updateColumnAria(ident);\n }\n }, function() {\n columnName.html(nameCache);\n nameCache = null;\n });\n } else {\n columnName.html(nameCache);\n nameCache = null;\n }\n }\n });\n }\n\n if (!isReadOnlyBoard) {\n const newNoteButton = $('
' +\n '
');\n columnNewContent.append(newNoteButton);\n if (column.attr('data-locked') === 'true') {\n newNoteButton.addClass('d-none');\n }\n handleAction(columnNewContent.find('.newnote'), function() {\n // We do not need to add firstname and lasname because we use ismynote and actual board user.\n addNote(ident, 0, null, null, null, {id: userId}, 0, 0);\n });\n }\n\n var lastOne = $(\".mod_board .board_column_hasdata\").last();\n if (lastOne.length) {\n column.insertAfter(lastOne);\n } else {\n $(\".mod_board\").append(column);\n }\n\n if (notes) {\n for (var index in notes) {\n let sortorder = sortby == 3 ? notes[index].sortorder : notes[index].timecreated;\n\n addNote(ident, notes[index].id, notes[index].heading, notes[index].content,\n {type: notes[index].type, info: notes[index].info, url: notes[index].url},\n {id: notes[index].userid, firstname: notes[index].firstname, lastname: notes[index].lastname},\n sortorder, notes[index].rating);\n }\n }\n sortNotes(columnContent);\n updateColumnAria(ident);\n if (isEditor || usersCanEdit == 1) {\n updateSortable();\n }\n if (isEditor) {\n columnSorting();\n }\n };\n\n /**\n * Gets the text name used in the heading of a column.\n * @param {number} id The ID data attribute on the column element.\n * @returns {string}\n */\n const getColumnName = (id) => {\n return $(`.board_column[data-ident='${id}']`).find('.mod_board_column_name').html();\n };\n\n /**\n * Add the new column button.\n *\n * @method addNewColumnButton\n */\n var addNewColumnButton = function() {\n var column = $('
'),\n newBusy = false;\n column.append('
');\n\n handleAction(column.find('.newcolumn'), function() {\n if (newBusy) {\n return;\n }\n newBusy = true;\n\n serviceCall('add_column', {boardid: board.id, name: strings.default_column_heading}, function(result) {\n addColumn(result.id, strings.default_column_heading, false, {}, selectHeadingColour());\n lastHistoryId = result.historyid;\n newBusy = false;\n }, function() {\n newBusy = false;\n });\n });\n\n $(\".mod_board\").append(column);\n };\n\n /**\n * This selects the next heading colour from options based on the count of the\n * current columns. Length of decremented by one as the new column button is\n * also denoted as a column.\n * @returns {string} colour hex string.\n */\n const selectHeadingColour = () => {\n let colCount = $('.board_column').length - 1;\n let colourCount = options.colours.length;\n return options.colours[colCount % colourCount];\n };\n\n /**\n * Update a note with the provided information.\n *\n * @method updateNote\n * @param {object} note\n * @param {string} heading\n * @param {object} data\n */\n var updateNote = function(note, heading, data) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n noteText.html(data.content);\n noteHeading.html(data.heading);\n setAttachment(note, data.attachment);\n updateNoteAria(data.id);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n };\n\n /**\n * Fetch and process the recent board history.\n *\n * @method processBoardHistory\n */\n var processBoardHistory = function() {\n serviceCall('board_history', {id: board.id, ownerid: ownerId, since: lastHistoryId}, function(boardhistory) {\n for (var index in boardhistory) {\n var item = boardhistory[index];\n if (item.boardid != board.id) {\n continue; // Hmm\n }\n\n var data = JSON.parse(item.content);\n if (item.action == 'add_note') {\n let sortorder = sortby == 3 ? data.sortorder : data.timecreated;\n addNote(data.columnid, data.id, data.heading, data.content, data.attachment,\n {id: item.userid}, sortorder, data.rating);\n updateNoteAria(data.id);\n sortNotes($('.board_column[data-ident=' + data.columnid + '] .board_column_content'));\n } else if (item.action == 'update_note') {\n let note = getNote(data.id),\n formModal = editModal,\n historyData = data;\n if (note) {\n let noteHeading = getNoteHeadingForNote(note);\n\n if (editingNote == data.id) {\n Notification.confirm(\n strings.note_changed_title, // Confirm.\n strings.note_changed_text, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n formModal.hide();\n updateNote(note, noteHeading, historyData);\n stopNoteEdit();\n }\n );\n } else {\n updateNote(note, noteHeading, data);\n }\n }\n } else if (item.action == 'delete_note') {\n if (editingNote == data.id) {\n Notification.alert(strings.warning, strings.note_deleted_text);\n stopNoteEdit();\n }\n let note = getNote(data.id);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n\n } else if (item.action == 'add_column') {\n addColumn(data.id, data.name, false, {}, selectHeadingColour());\n } else if (item.action == 'move_column') {\n const board = $('.mod_board');\n data.sortorder.forEach(column => {\n const columnElement = board.find(`.board_column[data-ident='${column}']`);\n columnElement.detach().appendTo(board);\n });\n } else if (item.action == 'update_column') {\n $(\".board_column[data-ident='\" + data.id + \"'] .mod_board_column_name\").html(data.name);\n updateColumnAria(data.id);\n } else if (item.action == 'lock_column') {\n $(\".board_column[data-ident='\" + data.id + \"']\").attr(\"data-locked\", data.locked);\n if (data.locked) {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').addClass('d-none');\n } else {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').removeClass('d-none');\n }\n updateSortable();\n } else if (item.action == 'delete_column') {\n var column = $(\".board_column[data-ident='\" + data.id + \"']\");\n if (editingNote && column.find('.board_note[data-ident=\"' + editingNote + '\"]').length) {\n stopNoteEdit();\n }\n column.remove();\n } else if (item.action == 'rate_note') {\n var note = getNote(data.id);\n note.find('.mod_board_rating').html(data.rating);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n lastHistoryId = item.id;\n }\n\n updateBoard();\n });\n };\n\n /**\n * Trigger a board update.\n *\n * @method updateBoard\n * @param {boolean} instant\n */\n var updateBoard = function(instant) {\n if (instant) {\n processBoardHistory();\n } else if (options.history_refresh > 0) {\n if (reloadTimer) {\n stopUpdating();\n }\n reloadTimer = setTimeout(processBoardHistory, options.history_refresh * 1000);\n }\n };\n\n /**\n * Stop/prevent the board reload timer from firing.\n *\n * @method stopUpdating\n */\n var stopUpdating = function() {\n clearTimeout(reloadTimer);\n reloadTimer = null;\n };\n\n /**\n * Sort a set of notes.\n *\n * @sortNotes\n * @param {string} content\n * @param {boolean} toggle\n */\n var sortNotes = function(content, toggle) {\n var sortCol = $(content).parent().find('.mod_board_column_sort'),\n direction = $(content).data('sort');\n if (!direction) {\n if (sortby == SORTBY_RATING) {\n direction = 'desc';\n } else {\n direction = 'asc';\n }\n }\n if (toggle) {\n direction = direction == 'asc' ? 'desc' : 'asc';\n }\n\n if (direction == 'asc') {\n sortCol.removeClass('fa-angle-down');\n sortCol.addClass('fa-angle-up');\n } else {\n sortCol.removeClass('fa-angle-up');\n sortCol.addClass('fa-angle-down');\n }\n $(content).data('sort', direction);\n\n var desc,\n asc;\n if (sortby == SORTBY_DATE) {\n desc = function(a, b) {\n return $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_RATING) {\n desc = function(a, b) {\n return $(b).find('.mod_board_rating').text() - $(a).find('.mod_board_rating').text() ||\n $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).find('.mod_board_rating').text() - $(b).find('.mod_board_rating').text() ||\n $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_NONE) {\n let sortElements = (a, b) => {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n $('> .board_note', $(content)).sort(sortElements).appendTo($(content));\n return;\n }\n\n $('> .board_note', $(content)).sort(direction === 'asc' ? asc : desc).appendTo($(content));\n\n };\n\n /**\n * Update sorting of sortable content.\n *\n * @method updateSortable\n */\n var updateSortable = function() {\n let fromColumnID;\n $(\".board_column[data-locked='false'] .board_column_content\").sortable({\n connectWith: \".board_column[data-locked='false'] .board_column_content\",\n cancel: \".mod_board_nosort\",\n handle: \".move_note\",\n start: function(_, ui) {\n fromColumnID = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n var note = $(ui.item),\n tocolumn = note.closest('.board_column'),\n elem = $(this),\n noteid = note.data('ident'),\n columnid = tocolumn.data('ident');\n let columnElements = tocolumn.find('.board_column_content').children();\n let sortorder = columnElements.index($(`.board_note[data-ident=${noteid}]`));\n let payload = {\n id: noteid,\n columnid: columnid,\n ownerid: ownerId,\n sortorder: sortorder\n };\n moveNote(fromColumnID, payload, elem);\n }\n });\n };\n\n /**\n * Move a note to a new position / column.\n *\n * @param {Int} fromColumnID The column the note is being moved from.\n * @param {Object} payload The payload to send to the server.\n * @param {Domnode} elem The element clicked to trigger the move.\n */\n const moveNote = (fromColumnID, payload, elem) => {\n updateSortOrders(fromColumnID, payload.columnid, payload.id, payload.sortorder);\n\n serviceCall('move_note', payload, (result) => {\n if (result.status) {\n lastHistoryId = result.historyid;\n updateNoteAria(payload.id);\n updateBoard();\n sortNotes($(`.board_column[data-ident=${payload.columnid}] .board_column_content`));\n } else {\n if (elem) {\n elem.sortable('cancel');\n }\n }\n });\n };\n\n /**\n * Enable column sorting\n */\n const columnSorting = () => {\n let movingColumnId;\n $(\".mod_board\").sortable({\n connectWith: \".mod_board\",\n axis: \"x\",\n containment: \".mod_board_wrapper\",\n cancel: \".mod_board_nosort\",\n handle: \".mod_column_move\",\n start: function(_, ui) {\n movingColumnId = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n let column = $(ui.item);\n let columns = $(\".mod_board\").find('.board_column');\n let sortorder = columns.index(column);\n let payload = {\n id: movingColumnId,\n sortorder: sortorder\n };\n moveColumn(payload);\n }\n });\n };\n\n /**\n * Move a column to a new position.\n *\n * @param {Object} payload The payload to send to the server.\n */\n const moveColumn = (payload) => {\n serviceCall('move_column', payload, false);\n };\n\n /**\n * Updates the inline data attributes necessary for rendering the lists\n * in the correct sort order. Note: the data attribute values updated by\n * jQuery are not reflected in DOM inspection but are still set.\n * @param {number} fromColumnID The column ID of the column to sort.\n * @param {number} toColumnID The column ID of the column to sort.\n * @param {number} noteID The note ID that was moved.\n * @param {number} newSortOrder The new position of the note sort order.\n */\n const updateSortOrders = (fromColumnID, toColumnID, noteID, newSortOrder) => {\n let toColumn = $(`.board_column[data-ident=${toColumnID}] .board_column_content`);\n let movedNote = $(`.board_note[data-ident=${noteID}]`);\n let oldSortOrder = movedNote.data('sortorder');\n // Check whether it is the same column and then increment or decrement notes above or below\n // then set sortorder according to whether the sortorder has moved up or down.\n let toChildren = toColumn.children();\n if (fromColumnID == toColumnID) {\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (oldSortOrder < newSortOrder) {\n if (sortOrder <= newSortOrder && sortOrder >= oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n } else if (oldSortOrder > newSortOrder) {\n if (sortOrder >= newSortOrder && sortOrder <= oldSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n }\n });\n } else {\n let fromColumn = $(`.board_column[data-ident=${fromColumnID}] .board_column_content`);\n let fromChildren = fromColumn.children();\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder >= newSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n });\n fromChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder > oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n });\n }\n movedNote.data('sortorder', newSortOrder);\n };\n\n /**\n * Get the body fragment for the modal form.\n *\n * @param {number} noteid\n * @param {number} columnid\n * @param {number} ownerId\n * @returns {Deferred|*}\n */\n var getBody = function(noteid, columnid, ownerId) {\n // Get the content of the modal.\n var params = {noteid: noteid, columnid: columnid, ownerid: ownerId};\n return Fragment.loadFragment('mod_board', 'note_form', contextid, params);\n };\n\n /**\n * Setup the aria labels for the modal.\n *\n * @param {object} note\n * @param {object} modal\n */\n var updateModalAria = function(note, modal) {\n let columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text(),\n addYoutube,\n addImage,\n addLink,\n postButton,\n cancelButton,\n modalRoot = modal.getRoot();\n\n if (note.data('ident')) {\n // Is a note update.\n var noteIdentifier = textIdentifierForNote(note);\n\n postButton = strings.aria_postedit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n cancelButton = strings.aria_canceledit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n addYoutube = strings.aria_addmedia.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addImage = strings.aria_addmedia.replace('{type}', strings.option_image).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addLink = strings.aria_addmedia.replace('{type}', strings.option_link).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n } else {\n // Note is new.\n postButton = strings.aria_postnew.replace('{column}', columnIdentifier);\n cancelButton = strings.aria_cancelnew.replace('{column}', columnIdentifier);\n addYoutube = strings.aria_addmedianew.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier);\n addImage = strings.aria_addmedianew.replace('{type}', strings.option_image).replace('{column}', columnIdentifier);\n addLink = strings.aria_addmedianew.replace('{type}', strings.option_link).replace('{column}', columnIdentifier);\n }\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('aria-label', addYoutube);\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('title', addYoutube);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('aria-label', addImage);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('title', addImage);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('aria-label', addLink);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('title', addLink);\n }\n\n let button = modalRoot.find(modal.getActionSelector('save'));\n if (button) {\n button.attr('aria-label', postButton);\n }\n button = modalRoot.find(modal.getActionSelector('cancel'));\n if (button) {\n button.attr('aria-label', cancelButton);\n }\n };\n\n /**\n * Displays the modal form to edit a note.\n *\n * @param {object} note\n */\n var showModalForm = function(note) {\n let noteId = 0,\n columnId = note.data('column'),\n column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n title;\n\n if (note.data('ident')) {\n noteId = note.data('ident');\n title = strings.modal_title_edit.replace('{column}', columnIdentifier);\n } else {\n title = strings.modal_title_new.replace('{column}', columnIdentifier);\n }\n\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: getBody(noteId, columnId, ownerId),\n large: true,\n removeOnClose: true\n }).then(function(modal) {\n // Use the body promise so we know body content is loaded.\n modal.getBodyPromise().then(function () {\n let saveInProgress = false;\n editModal = modal;\n modal.setLarge();\n modal.setSaveButtonText(strings.post_button_text);\n modal.setButtonText('cancel', strings.cancel_button_text);\n\n modal.getRoot().on(ModalEvents.hidden, function () {\n stopNoteEdit();\n if (!note.data('ident')) {\n note.remove();\n }\n });\n\n modal.getRoot().on(ModalEvents.save, function (e) {\n e.preventDefault();\n modal.getRoot().find('form').submit();\n });\n\n var changeEvent = document.createEvent('HTMLEvents');\n changeEvent.initEvent('change', true, true);\n\n modal.getRoot().on('submit', 'form', function (e) {\n e.preventDefault();\n\n // Prevent multiple form submissions from being sent.\n if (saveInProgress) {\n return;\n }\n saveInProgress = true;\n\n // First, make sure the native html5 validity checks are run.\n let valid = modal.getRoot().find('form').get(0).reportValidity();\n if (!valid) {\n saveInProgress = false;\n return;\n }\n\n // Prompt all inputs to run their validation functions.\n // Normally this would happen when the form is submitted, but\n // since we aren't submitting the form normally we need to run client side\n // validation.\n modal.getRoot().find(':input').each(function (index, element) {\n element.dispatchEvent(changeEvent);\n });\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n var invalid = $.merge(\n modal.getRoot().find('[aria-invalid=\"true\"]'),\n modal.getRoot().find('.error'),\n modal.getRoot().find(':invalid')\n );\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n saveInProgress = false;\n return;\n }\n\n var formData = JSON.stringify(modal.getRoot().find('form').serialize());\n serviceCall('submit_form', {contextid: contextid, jsonformdata: formData}, function (result) {\n if (result.status) {\n if (result.action == 'insert') {\n // Added a new note.\n lastHistoryId = result.historyid;\n note.remove();\n addNote(columnId, result.note.id, result.note.heading, result.note.content,\n {type: result.note.type, info: result.note.info, url: result.note.url},\n {id: result.note.userid}, result.note.timecreated, result.note.rating);\n sortNotes($('.board_column[data-ident=' + columnId + '] .board_column_content'));\n updateNoteAria(result.note.id);\n } else {\n // Updated existing note.\n lastHistoryId = result.historyid;\n getNoteTextForNote(note).html(result.note.content);\n getNoteHeadingForNote(note).html(result.note.heading);\n updateNoteAria(result.note.id);\n setAttachment(note, {\n type: result.note.type,\n info: result.note.info, url: result.note.url\n });\n }\n stopNoteEdit();\n\n // Clear the form changed checker.\n Y.use('moodle-core-formchangechecker', function() {\n M.core_formchangechecker.reset_form_dirty_state();\n });\n\n modal.destroy();\n } else {\n modal.destroy();\n }\n });\n\n });\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n // First hide the select menu.\n modal.getRoot().find('#fitem_id_mediatype').hide();\n\n let mediaSelect = modal.getRoot().find('#fitem_id_mediatype select'),\n ytButton = modal.getRoot().find('.mod_board_attachment_button.youtube_button'),\n pictureButton = modal.getRoot().find('.mod_board_attachment_button.image_button'),\n linkButton = modal.getRoot().find('.mod_board_attachment_button.link_button'),\n updateMediaButtons = function() {\n ytButton.removeClass('selected');\n pictureButton.removeClass('selected');\n linkButton.removeClass('selected');\n switch (mediaSelect.val()) {\n case (\"1\"):\n ytButton.addClass('selected');\n break;\n case (\"2\"):\n pictureButton.addClass('selected');\n break;\n case (\"3\"):\n linkButton.addClass('selected');\n break;\n }\n };\n\n updateMediaButtons();\n handleAction(ytButton, function() {\n if (mediaSelect.val() === \"1\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(1);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(pictureButton, function() {\n if (mediaSelect.val() === \"2\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(2);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(linkButton, function() {\n if (mediaSelect.val() === \"3\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(3);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n } else {\n modal.getRoot().find('#fitem_id_mediabuttons').hide();\n }\n\n updateModalAria(note, modal);\n modal.show();\n\n return modal;\n }).catch(Notification.exception);\n return modal;\n }).catch(Notification.exception);\n };\n\n /**\n * Show the note in a modal\n * @param {Int} ident The note id\n * @param {Object} notecontent The note content\n */\n var fullScreenNote = (ident, notecontent) => {\n const heading = getNoteHeadingForNote(notecontent).html();\n const modalBody = $(document.createElement('div'));\n modalBody.addClass('mod_board_note_content');\n const text = getNoteTextForNote(notecontent);\n if (text) {\n modalBody.append(text.clone());\n }\n const preview = getNotePreviewForNote(notecontent);\n if (preview) {\n modalBody.append(preview.clone());\n }\n\n // Adds the comments to a note.\n const commentArea = $(document.createElement('div'));\n commentArea.attr('data-region', 'comment-area');\n modalBody.append(commentArea);\n Comments.fetchFor(ident, commentArea);\n\n ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: heading,\n body: modalBody,\n }).then(function(modal) {\n modal.setLarge();\n modal.show();\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function () {\n // Destroy when hidden.\n modal.destroy();\n });\n return modal;\n }, this).catch(Notification.exception);\n };\n\n /**\n * Initialize board.\n *\n * @method init\n */\n var init = function() {\n serviceCall('get_board', {id: board.id, ownerid: ownerId}, function(columns) {\n // Init\n if (columns) {\n for (var index in columns) {\n addColumn(\n columns[index].id,\n columns[index].name,\n columns[index].locked,\n columns[index].notes || {},\n options.colours[columns[index].id % options.colours.length]\n );\n }\n }\n\n if (isEditor) {\n addNewColumnButton();\n }\n\n lastHistoryId = board.historyid;\n\n if (isEditor) {\n updateSortable();\n columnSorting();\n }\n\n updateBoard();\n });\n };\n\n // Get strings\n var stringsInfo = [];\n for (var string in strings) {\n stringsInfo.push({key: string, component: 'mod_board'});\n }\n\n $.when(getStrings(stringsInfo)).done(function(results) {\n var index = 0;\n for (string in strings) {\n strings[string] = results[index++];\n }\n\n init();\n });\n}\n"],"names":["settings","strings","default_column_heading","post_button_text","cancel_button_text","remove_note_title","remove_note_text","remove_column_title","note_changed_title","note_changed_text","note_deleted_text","rate_note_title","rate_note_text","rate_remove_note_text","Ok","delete","Cancel","warning","modal_title_new","modal_title_edit","option_youtube","option_image","option_link","aria_newcolumn","aria_newpost","aria_deletecolumn","aria_movecolumn","aria_deletepost","aria_movepost","aria_editpost","aria_addmedia","aria_addmedianew","aria_deleteattachment","aria_postedit","aria_canceledit","aria_postnew","aria_cancelnew","aria_ratepost","invalid_file_extension","invalid_file_size_min","invalid_file_size_max","invalid_youtube_url","options","JSON","parse","board","contextid","reloadTimer","lastHistoryId","isEditor","usersCanEdit","userId","parseInt","userFirstname","firstname","userLastname","lastname","ownerId","mediaSelection","mediaselection","editingNote","isReadOnlyBoard","readonly","showauthorofnote","ratingenabled","sortby","editModal","enableblanktarget","serviceCall","method","args","callback","failcallback","stopUpdating","call","methodname","done","data","fail","error","exception","_serviceCall","apply","arguments","updateBoard","getNote","ident","getNoteTextForNote","note","find","getNoteHeadingForNote","getNoteBorderForNote","getNoteAttachmentsForNote","textIdentifierForNote","noteText","html","noteHeading","noteAttachment","attachmentDataForNote","length","replace","split","slice","join","info","updateNoteAria","noteId","columnIdentifier","closest","text","noteIdentifier","deleteNoteString","attr","moveNoteString","editNoteString","updateColumnAria","columnId","column","newNoteString","moveColumnString","deleteColumnString","each","index","stopNoteEdit","noteBorder","show","hide","remove","sortAfterDelete","columnID","sortorder","getColumn","children","filter","_","element","so","setAttachment","attachment","type","attType","val","decodeText","url","attachmentInfo","attachmentUrl","attachmentFile","prop","attachmentTypeToString","FileReader","attachmentTypeChanged","previewAttachment","filename","filecontents","encodeText","fileElem","elem","removeClass","addClass","blanktarget","videoID","match","undefined","getEmbedUrl","addNote","columnid","heading","content","owner","rating","ismynote","id","iseditable","pendingNote","notecontent","notecontrols","noteAuthorusername","noteAriaText","attachmentPreview","append","columnContent","beginEdit","showModalForm","startNoteEdit","rateElement","handleAction","result","canrate","rateRemoveText","hasrated","confirm","status","historyid","sortNotes","then","rateModal","getRoot","on","ModalEvents","hidden","rateNote","removeElement","deleteNote","moveElement","init","moveNote","editElement","updateSortable","fullScreenNote","lastOne","last","insertAfter","prepend","addColumn","name","locked","notes","colour","headerStyle","nameCache","columnHeader","columnSort","columnName","columnNewContent","hideheaders","lockIcon","lockElement","lockstring","str","lockColumn","moveColumn","getColumnName","callBeforeOnKeyEditing","is","Error","e","isAriaTriggerKey","keyCode","preventDefault","editable","handleEditableAction","toggleFontSize","closeOnEnter","newNoteButton","noteicon","timecreated","userid","columnSorting","selectHeadingColour","colCount","colourCount","colours","updateNote","processBoardHistory","ownerid","since","boardhistory","item","boardid","action","formModal","historyData","alert","forEach","detach","appendTo","instant","history_refresh","setTimeout","clearTimeout","toggle","desc","asc","sortCol","parent","direction","a","b","sortElements","sort","fromColumnID","sortable","connectWith","cancel","handle","start","ui","stop","tocolumn","this","noteid","payload","updateSortOrders","movingColumnId","axis","containment","toColumnID","noteID","newSortOrder","toColumn","movedNote","oldSortOrder","toChildren","sortOrder","fromChildren","getBody","params","Fragment","loadFragment","title","create","ModalFactory","types","SAVE_CANCEL","body","large","removeOnClose","modal","getBodyPromise","saveInProgress","setLarge","setSaveButtonText","setButtonText","save","submit","changeEvent","document","createEvent","initEvent","get","reportValidity","dispatchEvent","invalid","$","merge","first","focus","formData","stringify","serialize","jsonformdata","Y","use","M","core_formchangechecker","reset_form_dirty_state","destroy","mediaSelect","ytButton","pictureButton","linkButton","updateMediaButtons","addYoutube","addImage","addLink","postButton","cancelButton","modalRoot","button","getActionSelector","updateModalAria","catch","Notification","modalBody","createElement","clone","preview","commentArea","fetchFor","CANCEL","columns","newBusy","columnicon","stringsInfo","string","push","key","component","when","results","rawText","encodedText"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"board.min.js","sources":["../src/board.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle the board.\n *\n * @author Karen Holland \n * @copyrigt 2021 Brickfield Education Labs \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from \"jquery\";\nimport {get_strings as getStrings, get_string as getString} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport ModalFactory from \"core/modal_factory\";\nimport ModalEvents from \"core/modal_events\";\nimport Notification from \"core/notification\";\nimport \"mod_board/jquery.editable.amd\";\nimport \"mod_board/jquery.sortable.amd\";\nimport Fragment from \"core/fragment\";\nimport Comments from \"mod_board/comments\";\nimport moveNotesDialog from \"./movenotesdialog\";\nimport moveColumnsDialog from \"./movecolumnsdialog\";\n\n/**\n * Execute a ajax call to a mod_board ajax service.\n *\n * @param {string} method\n * @param {array} args\n * @param {method} callback\n * @param {method} failcallback\n * @private\n */\nconst _serviceCall = function(method, args, callback, failcallback) {\n Ajax.call([{\n methodname: 'mod_board_' + method,\n args: args,\n done: function(data) {\n callback(data);\n },\n fail: function(error) {\n Notification.exception(error);\n if (failcallback) {\n failcallback(error);\n }\n }\n }]);\n};\n\n/**\n * Indicates if this is a keycode we want to listend to for\n * aria purposes.\n *\n * @returns {boolean}\n * @param {number} key\n */\nconst isAriaTriggerKey = function(key) {\n return key == 13 || key == 32;\n};\n\n/**\n * Encodes text into html entities.\n *\n * @param {string} rawText\n * @returns {*|jQuery}\n */\nconst encodeText = function(rawText) {\n return $('
').text(rawText).html();\n};\n\n/**\n * Decodes text from html entities.\n *\n * @param {string} encodedText\n * @returns {*|jQuery}\n */\nconst decodeText = function(encodedText) {\n return $('
').html(encodedText).text();\n};\n\n/**\n * Handler for keypress and click actions.\n *\n * @param {object} elem\n * @param {function} callback\n * @returns {*}\n */\nconst handleAction = function(elem, callback) {\n return elem.on('click keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode)) {\n e.preventDefault();\n } else {\n return;\n }\n }\n\n callback();\n e.preventDefault();\n });\n};\n\n/**\n * Setting up element edibility.\n *\n * @param {object} elem\n * @param {function} callback\n * @param {function} callBeforeOnKeyEditing\n * @returns {*}\n */\nconst handleEditableAction = function(elem, callback, callBeforeOnKeyEditing) {\n if (elem.is(':editable')) {\n throw new Error('handleEditableAction - must be called before setting the element as editable');\n }\n\n // Can't use on(edit) here because we want to do actions (save cache) before the control goes into edit mode\n return elem.on('dblclick keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode) && !elem.is(':editing')) {\n e.preventDefault();\n if (callBeforeOnKeyEditing) {\n callback();\n }\n elem.editable('open');\n if (callBeforeOnKeyEditing) {\n return;\n }\n } else {\n return;\n }\n }\n\n callback();\n });\n};\n\n/**\n * The default function of the module, which does the setup of the page.\n *\n * @param {object} settings\n */\nexport default function(settings) {\n // An array of strings to load as a batch later.\n // Not necessary, but used to load all the strings in one ajax call.\n var strings = {\n default_column_heading: '',\n post_button_text: '',\n cancel_button_text: '',\n remove_note_title: '',\n remove_note_text: '',\n remove_column_title: '',\n note_changed_title: '',\n note_changed_text: '',\n note_deleted_text: '',\n rate_note_title: '',\n rate_note_text: '',\n rate_remove_note_text: '',\n Ok: '',\n delete: '',\n Cancel: '',\n warning: '',\n modal_title_new: '',\n modal_title_edit: '',\n option_youtube: '',\n option_image: '',\n option_link: '',\n\n aria_newcolumn: '',\n aria_newpost: '',\n aria_deletecolumn: '',\n aria_movecolumn: '',\n aria_deletepost: '',\n aria_movepost: '',\n aria_editpost: '',\n aria_addmedia: '',\n aria_addmedianew: '',\n aria_deleteattachment: '',\n aria_postedit: '',\n aria_canceledit: '',\n aria_postnew: '',\n aria_cancelnew: '',\n aria_ratepost: '',\n\n invalid_file_extension: '',\n invalid_file_size_min: '',\n invalid_file_size_max: '',\n\n invalid_youtube_url: '',\n };\n\n // Json decode the strings from the settings.\n var options = JSON.parse(settings.settings) || {};\n var board = options.board || {};\n var contextid = options.contextid;\n\n const MEDIA_SELECTION_BUTTONS = 1,\n ATTACHMENT_VIDEO = 1,\n ATTACHMENT_IMAGE = 2,\n ATTACHMENT_LINK = 3,\n SORTBY_DATE = 1,\n SORTBY_RATING = 2,\n SORTBY_NONE = 3;\n\n var reloadTimer = null,\n lastHistoryId = null,\n isEditor = options.isEditor || false,\n usersCanEdit = options.usersCanEdit,\n userId = parseInt(options.userId) || -1,\n userFullname = options.userFullname,\n ownerId = parseInt(options.ownerId),\n mediaSelection = options.mediaselection || MEDIA_SELECTION_BUTTONS,\n editingNote = 0,\n isReadOnlyBoard = options.readonly || false,\n showauthorofnote = options.showauthorofnote || false,\n allowshowauthorofnoteonboard = options.allowshowauthorofnoteonboard || false,\n ratingenabled = options.ratingenabled,\n sortby = options.sortby || SORTBY_DATE,\n editModal = null,\n enableblanktarget = (parseInt(options.enableblanktarget) === 1);\n\n /**\n * Helper method to make calls to mod_board external services.\n *\n * @param {string} method\n * @param {array} args\n * @param {function} callback\n * @param {function} failcallback\n */\n var serviceCall = function(method, args, callback, failcallback) {\n if (method !== 'board_history') {\n stopUpdating();\n }\n _serviceCall(method, args, function() {\n if (callback) {\n callback.apply(null, arguments);\n }\n if (method !== 'board_history' && method != 'get_board') {\n updateBoard(true);\n }\n }, failcallback);\n };\n\n /**\n * Returns the jquery element of a given note identifier.\n *\n * @param {number} ident\n * @returns {jQuery}\n */\n var getNote = function(ident) {\n return $(\".board_note[data-ident='\" + ident + \"']\");\n };\n\n /**\n * Returns the jquery element of the note text for the given note element.\n *\n * @method getNoteTextForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteTextForNote = function(note) {\n return $(note).find(\".mod_board_note_text\");\n };\n\n /**\n * Returns the jquery element of the preview for the given note element.\n *\n * @method getNotePreviewForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNotePreviewForNote = (note) => {\n return $(note).find(\".mod_board_preview\");\n };\n\n\n /**\n * Returns the jquery element of the note heading for the given note element.\n *\n * @method getNoteHeadingForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteHeadingForNote = function(note) {\n return $(note).find(\".mod_board_note_heading\");\n };\n\n /**\n * Returns the jquery element of the note border for the given note element.\n *\n * @method getNoteBorderForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteBorderForNote = function(note) {\n return $(note).find(\".mod_board_note_border\");\n };\n\n /**\n * Gets a jquery node for the attachments of a given note.\n *\n * @method getNoteAttachmentsForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteAttachmentsForNote = function(note) {\n return $(note).find(\".mod_board_note_attachment\");\n };\n\n /**\n * Creates text identifier for a given node.\n *\n * @method textIdentifierForNote\n * @param {object} note\n * @returns {null|*|jQuery}\n */\n var textIdentifierForNote = function(note) {\n var noteText = getNoteTextForNote(note).html(),\n noteHeading = getNoteHeadingForNote(note).html(),\n noteAttachment = attachmentDataForNote(note);\n\n if (noteHeading.length > 0) {\n return noteHeading;\n }\n if (noteText.length > 0) {\n return noteText.replace(//gi, \" \").replace(/\\n/g, \" \").split(/\\s+/).slice(0, 5).join(\" \");\n }\n if (noteAttachment.info && noteAttachment.info.length > 0) {\n return noteAttachment.info;\n }\n return null;\n };\n\n /**\n * Update the Aria info for a given note id.\n *\n * @method updateNoteAria\n * @param {number} noteId\n */\n var updateNoteAria = function(noteId) {\n var note = getNote(noteId),\n columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text();\n\n if (noteId) { // New post\n var noteIdentifier = textIdentifierForNote(note),\n deleteNoteString = strings.aria_deletepost.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n\n note.find('.delete_note').attr('aria-label', deleteNoteString).attr('title', deleteNoteString);\n\n var moveNoteString = strings.aria_movepost.replace('{post}', noteIdentifier);\n note.find('.move_note').attr('aria-label', moveNoteString).attr('title', moveNoteString);\n\n var editNoteString = strings.aria_editpost.replace('{post}', noteIdentifier);\n note.find('.edit_note').attr('aria-label', editNoteString).attr('title', editNoteString);\n\n note.find('.mod_board_rating').attr('aria-label', strings.aria_ratepost.replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier));\n note.find('.note_ariatext').html(noteIdentifier);\n }\n\n };\n\n /**\n * Update the Aria information for a given column id.\n *\n * @method updateColumnAria\n * @param {number} columnId\n */\n var updateColumnAria = function(columnId) {\n var column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n newNoteString = strings.aria_newpost.replace('{column}', columnIdentifier),\n moveColumnString = strings.aria_movecolumn.replace('{column}', columnIdentifier),\n deleteColumnString = strings.aria_deletecolumn.replace('{column}', columnIdentifier);\n column.find('.newnote').attr('aria-label', newNoteString).attr('title', newNoteString);\n column.find('.mod_column_move').attr('aria-label', moveColumnString).attr('title', moveColumnString);\n column.find('.delete_column').attr('aria-label', deleteColumnString).attr('title', deleteColumnString);\n\n column.find(\".board_note\").each(function(index, note) {\n updateNoteAria($(note).data('ident'));\n });\n };\n\n /**\n * Stop the current note editing process.\n *\n * @method stopNoteEdit\n */\n var stopNoteEdit = function() {\n if (!editingNote) {\n getNote(0).remove();\n return;\n }\n\n var note = getNote(editingNote);\n\n if (note) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n }\n\n editingNote = 0;\n };\n\n /**\n * Start the editing of a particular note, by identifier.\n *\n * @method startNoteEdit\n * @param {number} ident\n */\n var startNoteEdit = function(ident) {\n\n if (editingNote) {\n if (editingNote == ident) {\n return;\n }\n stopNoteEdit();\n }\n\n if (ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n var note = getNote(ident);\n if (note) {\n showModalForm(note);\n\n if (ident) {\n editingNote = ident;\n }\n }\n };\n\n /**\n * Delete a given note, by identifier.\n *\n * @method deleteNote\n * @param {number} ident\n */\n var deleteNote = function(ident) {\n Notification.confirm(\n strings.remove_note_title, // Are you sure?\n strings.remove_note_text, // This will effect others.\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_note', { id: ident }, function (result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n let note = getNote(ident);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n }\n });\n }\n );\n };\n\n /**\n * This function gets a board column as a jQuery element.\n * @param {number} columnID The column ID.\n * @returns {jQuery}\n */\n const getColumn = (columnID) => {\n return $(`.board_column[data-ident='${columnID}'] .board_column_content`);\n };\n\n const sortAfterDelete = (columnID, sortorder) => {\n let column = getColumn(columnID);\n let elements = column.children().filter((_, element) => {\n return parseInt($(element).data('sortorder')) > parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so - 1);\n });\n };\n\n /**\n * Rate (star) a give note, by identifier.\n *\n * @method rateNote\n * @param {number} ident\n */\n var rateNote = function(ident) {\n if (!ratingenabled) {\n return;\n }\n if (isReadOnlyBoard) {\n return;\n }\n\n var note = getNote(ident),\n rating = note.find('.mod_board_rating');\n if (rating.data('disabled')) {\n return;\n }\n rating.data('disabled', true);\n\n serviceCall('can_rate_note', {id: ident}, function(result) {\n if (result.canrate) {\n const rateRemoveText = result.hasrated ? strings.rate_remove_note_text : strings.rate_note_text;\n Notification.confirm(\n strings.rate_note_title,\n rateRemoveText, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n serviceCall('rate_note', {id: ident}, function(result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n rating.html(` ${result.rating} `);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n rating.data('disabled', false);\n });\n }\n ).then(function(rateModal) {\n // Do this here, because it catches both cancel clicks, or someone clicking the X.\n rateModal.getRoot().on(ModalEvents.hidden, function() {\n rating.data('disabled', false);\n });\n });\n }\n });\n };\n\n /**\n * Update the attachment information of a note.\n *\n * @method attachmentTypeChanged\n * @param {object} note\n */\n var attachmentTypeChanged = function(note) {\n var noteAttachment = getNoteAttachmentsForNote(note),\n type = noteAttachment.find('.mod_board_type').val(),\n attachmentInfo = noteAttachment.find('.info'),\n attachmentUrl = noteAttachment.find('.url'),\n attachmentFile = noteAttachment.find('.mod_board_file');\n\n if (type > \"0\") {\n attachmentInfo.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_info']);\n attachmentUrl.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_url']);\n\n attachmentInfo.show();\n if (type == ATTACHMENT_IMAGE && FileReader) {\n attachmentFile.show();\n attachmentUrl.hide();\n } else {\n attachmentFile.hide();\n attachmentUrl.show();\n }\n } else {\n attachmentInfo.hide();\n attachmentUrl.hide();\n attachmentFile.hide();\n\n attachmentInfo.val('');\n attachmentUrl.val('');\n\n }\n };\n\n /**\n * Set the attachment of a note.\n *\n * @method setAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var setAttachment = function(note, attachment) {\n var noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment) {\n if (!attachment) {\n attachment = {type: \"0\"};\n } else {\n attachment.type += \"\";// Just in case\n }\n var attType = noteAttachment.find('.mod_board_type');\n attType.val(attachment.type ? attachment.type : \"0\");\n if (attType.val() > \"0\") {\n noteAttachment.find('.info').val(decodeText(attachment.info));\n noteAttachment.find('.url').val(decodeText(attachment.url));\n }\n attachmentTypeChanged(note, attachment);\n }\n previewAttachment(note, attachment);\n };\n\n /**\n * Returns an object with various information about a note's attachment.\n *\n * @method attachmentDataForNote\n * @param {object} note\n * @returns {{filename: null, filecontents: null, type: number, url: null, info: null}}\n */\n var attachmentDataForNote = function(note) {\n var attachment = {type: 0, info: null, url: null, filename: null, filecontents: null},\n noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment.length) {\n attachment.type = noteAttachment.find('.mod_board_type').val();\n attachment.info = encodeText(noteAttachment.find('.info').val());\n attachment.url = encodeText(noteAttachment.find('.url').val());\n var fileElem = noteAttachment.find('.mod_board_file>input');\n if (fileElem.data('filename')) {\n attachment.filename = fileElem.data('filename');\n attachment.filecontents = fileElem.data('filecontents');\n }\n }\n if ((!attachment.info || !attachment.info.length) && (!attachment.url || !attachment.url.length) &&\n (!attachment.filename)) {\n attachment.type = 0;\n }\n\n return attachment;\n };\n\n /**\n * Get the string type of a attachment type number.\n *\n * @method attachmentTypeToString\n * @param {number} type\n * @returns {string|null}\n */\n var attachmentTypeToString = function(type) {\n switch (type) {\n case \"1\": return 'youtube';\n case \"2\": return 'image';\n case \"3\": return 'link';\n default: return null;\n }\n };\n\n /**\n * This parses a youtube video ID from a URL. We can use this ID to\n * construct the embed URL.\n * @param {string} url The URL entered to the modal.\n * @returns {string | null} The youtube embed URL or null.\n */\n const getEmbedUrl = (url) => {\n // Thanks for the regex from: https://gist.github.com/rodrigoborgesdeoliveira/987683cfbfcc8d800192da1e73adc486.\n let regex = /(\\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/;\n let videoID = url.match(regex);\n if (!videoID || videoID[2] === undefined || videoID[2].length !== 11) {\n return null;\n }\n return `https://www.youtube-nocookie.com/embed/${videoID[2]}`;\n };\n\n /**\n * Display the attachment preview for a note.\n *\n * @method previewAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var previewAttachment = function(note, attachment) {\n var elem = note.find('.mod_board_preview');\n if (!attachment) {\n attachment = attachmentDataForNote(note);\n }\n\n if (!getNoteTextForNote(note).html().length) {\n elem.addClass('mod_board_notext');\n } else {\n elem.removeClass('mod_board_notext');\n }\n\n elem.removeClass('wrapper_youtube');\n elem.removeClass('wrapper_image');\n elem.removeClass('wrapper_url');\n if (attachment.filename && parseInt(attachment.type) == ATTACHMENT_IMAGE) { // Before uploading\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n } else if (attachment.url) {\n const blanktarget = enableblanktarget ? ' target=\"_blank\"' : '';\n switch (parseInt(attachment.type)) {\n case ATTACHMENT_VIDEO: { // Youtube\n let url = getEmbedUrl(attachment.url);\n if (url === null) {\n elem.html(strings.invalid_youtube_url);\n } else {\n elem.html('');\n elem.addClass('wrapper_youtube').addClass('position-relative');\n }\n elem.show();\n }\n break;\n case ATTACHMENT_IMAGE: // Image\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n break;\n case ATTACHMENT_LINK: // Url\n elem.html('' +\n (attachment.info || attachment.url) + '');\n elem.addClass('wrapper_url');\n elem.show();\n break;\n default:\n elem.html('');\n elem.hide();\n }\n } else {\n elem.html('');\n elem.hide();\n }\n };\n\n /**\n * Add a new note with the given information.\n *\n * @method addNote\n * @param {number} columnid\n * @param {number} ident\n * @param {string} heading\n * @param {string} content\n * @param {object} attachment\n * @param {object} owner the owner of the note containing the userid as id and the owner fullname\n * @param {number} sortorder\n * @param {string} rating\n */\n var addNote = function(columnid, ident, heading, content, attachment, owner, sortorder, rating) {\n var ismynote = owner.id == userId || !ident;\n var iseditable = isEditor || (ismynote && !isReadOnlyBoard);\n\n if (!ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n // Making space for this note if necessary in the sort order.\n if (sortby == SORTBY_NONE) {\n let children = $(`.board_column[data-ident='${columnid}'] .board_column_content`).children();\n let elements = children.filter((_, element) => {\n return parseInt($(element).data('sortorder')) >= parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so + 1);\n });\n }\n\n var note = $('
');\n if (ismynote) {\n note.addClass('mod_board_mynote');\n }\n if (iseditable) {\n note.addClass('mod_board_editablenote');\n }\n if (!ismynote && !iseditable) {\n note.addClass('mod_board_nosort');\n }\n\n var notecontent = $('
'),\n notecontrols = $('
'),\n noteHeading = $('
' + (heading ? heading : '') + '
'),\n noteAuthorusername = $(''),\n noteBorder = $('
'),\n noteText = $('
' + (content ? content : '') + '
'),\n noteAriaText = $('
'),\n attachmentPreview = $('
');\n\n if (allowshowauthorofnoteonboard == true && showauthorofnote == true) {\n let fullname = '';\n if (ismynote) {\n // Use the Name of the user itself. We do not need to get this information from somewhere else.\n fullname = userFullname;\n } else {\n fullname = owner.fullname;\n }\n\n noteAuthorusername = '
' +\n ' ' +\n '' +\n fullname +\n '' +\n '
' ;\n }\n\n notecontent.append(noteHeading);\n notecontent.append(noteAuthorusername);\n notecontent.append(noteBorder);\n notecontent.append(noteText);\n notecontent.append(noteAriaText);\n\n notecontent.append(attachmentPreview);\n note.append(notecontent);\n\n var columnContent = $('.board_column[data-ident=' + columnid + '] .board_column_content');\n\n var beginEdit = () => {\n startNoteEdit(ident);\n };\n\n if (ident) {\n if (ratingenabled) {\n note.addClass('mod_board_rateablenote');\n var rateElement = $(`
${rating}
`);\n\n handleAction(rateElement, () => {\n rateNote(ident);\n });\n notecontrols.append(rateElement);\n }\n\n if (iseditable) {\n var removeElement = $('
');\n handleAction(removeElement, () => {\n deleteNote(ident);\n });\n\n notecontrols.append(removeElement);\n\n if (usersCanEdit == 1 || isEditor) {\n var moveElement = $('
');\n notecontrols.append(moveElement);\n moveNotesDialog.init(ownerId, moveNote);\n }\n\n var editElement = $('
');\n notecontrols.append(editElement);\n handleAction(editElement, () => {\n beginEdit();\n });\n updateSortable();\n setAttachment(note, attachment);\n } else {\n previewAttachment(note, attachment);\n }\n\n note.append(notecontrols);\n\n handleAction(notecontent, () => fullScreenNote(ident, notecontent));\n\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n\n var lastOne = columnContent.find(\".board_note\").last();\n\n if (lastOne.length) {\n note.insertAfter(lastOne);\n } else {\n columnContent.prepend(note);\n }\n } else {\n $('.board_column[data-ident=' + columnid + '] .board_column_newcontent').append(note);\n // This is effectively a note placeholder. So we don't need to show it.\n note.hide();\n beginEdit();\n }\n };\n\n /**\n * Add a new column.\n *\n * @method addColumn\n * @param {object} ident\n * @param {string} name\n * @param {bool} locked\n * @param {array} notes\n * @param {string} colour\n */\n var addColumn = function(ident, name, locked, notes, colour) {\n let headerStyle = `style=\"border-top: 10px solid #${colour}\"`;\n var iseditable = isEditor,\n nameCache = null,\n column = $(`
`),\n columnHeader = $('
'),\n columnSort = $('
'),\n columnName = $('
' + name + '
'),\n columnContent = $('
'),\n columnNewContent = $('
');\n // Only add the sort button if it makes sense.\n if (sortby != SORTBY_NONE) {\n columnHeader.append(columnSort);\n }\n columnHeader.append(columnName);\n\n if (options.hideheaders) {\n columnName.addClass('d-none');\n }\n\n columnSort.on('click', function() {\n sortNotes(columnContent, true);\n });\n\n if (iseditable) {\n column.addClass('mod_board_editablecolumn');\n const lockIcon = locked ? 'fa-lock' : 'fa-unlock';\n const lockElement = $(`
`);\n const lockstring = locked ? 'aria_column_locked' : 'aria_column_unlocked';\n getString(lockstring, 'mod_board', name).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n\n handleAction(lockElement, () => {\n const lockColumn = column.attr('data-locked') !== 'true';\n serviceCall('lock_column', {id: ident, status: lockColumn}, function(result) {\n const columnName = column.find('.mod_board_column_name').text();\n if (result.status) {\n if (lockColumn) {\n lockElement.removeClass('fa-unlock').addClass('fa-lock');\n column.attr('data-locked', 'true');\n column.find('.board_button.newnote').addClass('d-none');\n getString('aria_column_locked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n } else {\n lockElement.removeClass('fa-lock').addClass('fa-unlock');\n column.attr('data-locked', 'false');\n column.find('.board_button.newnote').removeClass('d-none');\n getString('aria_column_unlocked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n }\n lastHistoryId = result.historyid;\n updateSortable();\n }\n });\n });\n columnHeader.append(lockElement);\n\n columnHeader.addClass('icon-size-3');\n const moveElement = $('
');\n columnHeader.append(moveElement);\n moveColumnsDialog.init(moveColumn);\n var removeElement = $('
');\n handleAction(removeElement, () => {\n Notification.confirm(\n strings.remove_column_title, // Are you sure?\n getString('remove_column_text', 'mod_board', getColumnName(ident)),\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_column', {id: ident}, function(result) {\n if (result.status) {\n column.remove();\n lastHistoryId = result.historyid;\n }\n });\n }\n );\n });\n\n columnHeader.append(removeElement);\n }\n\n column.append(columnHeader);\n column.append(columnContent);\n column.append(columnNewContent);\n\n if (iseditable) {\n handleEditableAction(columnName, function() {\n nameCache = columnName.html();\n }, true);\n\n columnName.editable({\n toggleFontSize: false,\n closeOnEnter: true,\n callback: function(data) {\n if (data.content) {\n serviceCall('update_column', {id: ident, name: columnName.html()}, function(result) {\n if (!result.status) {\n columnName.html(nameCache);\n nameCache = null;\n } else {\n lastHistoryId = result.historyid;\n updateColumnAria(ident);\n }\n }, function() {\n columnName.html(nameCache);\n nameCache = null;\n });\n } else {\n columnName.html(nameCache);\n nameCache = null;\n }\n }\n });\n }\n\n if (!isReadOnlyBoard) {\n const newNoteButton = $('
' +\n '
');\n columnNewContent.append(newNoteButton);\n if (column.attr('data-locked') === 'true') {\n newNoteButton.addClass('d-none');\n }\n handleAction(columnNewContent.find('.newnote'), function() {\n // We do not need to add fullname to the owner because we use ismynote and the fullname of the actual board user.\n addNote(ident, 0, null, null, null, {id: userId}, 0, 0);\n });\n }\n\n var lastOne = $(\".mod_board .board_column_hasdata\").last();\n if (lastOne.length) {\n column.insertAfter(lastOne);\n } else {\n $(\".mod_board\").append(column);\n }\n\n if (notes) {\n for (var index in notes) {\n let sortorder = sortby == 3 ? notes[index].sortorder : notes[index].timecreated;\n\n addNote(ident, notes[index].id, notes[index].heading, notes[index].content,\n {type: notes[index].type, info: notes[index].info, url: notes[index].url},\n {id: notes[index].userid, fullname: notes[index].fullname},\n sortorder, notes[index].rating);\n }\n }\n sortNotes(columnContent);\n updateColumnAria(ident);\n if (isEditor || usersCanEdit == 1) {\n updateSortable();\n }\n if (isEditor) {\n columnSorting();\n }\n };\n\n /**\n * Gets the text name used in the heading of a column.\n * @param {number} id The ID data attribute on the column element.\n * @returns {string}\n */\n const getColumnName = (id) => {\n return $(`.board_column[data-ident='${id}']`).find('.mod_board_column_name').html();\n };\n\n /**\n * Add the new column button.\n *\n * @method addNewColumnButton\n */\n var addNewColumnButton = function() {\n var column = $('
'),\n newBusy = false;\n column.append('
');\n\n handleAction(column.find('.newcolumn'), function() {\n if (newBusy) {\n return;\n }\n newBusy = true;\n\n serviceCall('add_column', {boardid: board.id, name: strings.default_column_heading}, function(result) {\n addColumn(result.id, strings.default_column_heading, false, {}, selectHeadingColour());\n lastHistoryId = result.historyid;\n newBusy = false;\n }, function() {\n newBusy = false;\n });\n });\n\n $(\".mod_board\").append(column);\n };\n\n /**\n * This selects the next heading colour from options based on the count of the\n * current columns. Length of decremented by one as the new column button is\n * also denoted as a column.\n * @returns {string} colour hex string.\n */\n const selectHeadingColour = () => {\n let colCount = $('.board_column').length - 1;\n let colourCount = options.colours.length;\n return options.colours[colCount % colourCount];\n };\n\n /**\n * Update a note with the provided information.\n *\n * @method updateNote\n * @param {object} note\n * @param {string} heading\n * @param {object} data\n */\n var updateNote = function(note, heading, data) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n noteText.html(data.content);\n noteHeading.html(data.heading);\n setAttachment(note, data.attachment);\n updateNoteAria(data.id);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n };\n\n /**\n * Fetch and process the recent board history.\n *\n * @method processBoardHistory\n */\n var processBoardHistory = function() {\n serviceCall('board_history', {id: board.id, ownerid: ownerId, since: lastHistoryId}, function(boardhistory) {\n for (var index in boardhistory) {\n var item = boardhistory[index];\n if (item.boardid != board.id) {\n continue; // Hmm\n }\n\n var data = JSON.parse(item.content);\n if (item.action == 'add_note') {\n let sortorder = sortby == 3 ? data.sortorder : data.timecreated;\n addNote(data.columnid, data.id, data.heading, data.content, data.attachment,\n {id: item.userid}, sortorder, data.rating);\n updateNoteAria(data.id);\n sortNotes($('.board_column[data-ident=' + data.columnid + '] .board_column_content'));\n } else if (item.action == 'update_note') {\n let note = getNote(data.id),\n formModal = editModal,\n historyData = data;\n if (note) {\n let noteHeading = getNoteHeadingForNote(note);\n\n if (editingNote == data.id) {\n Notification.confirm(\n strings.note_changed_title, // Confirm.\n strings.note_changed_text, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n formModal.hide();\n updateNote(note, noteHeading, historyData);\n stopNoteEdit();\n }\n );\n } else {\n updateNote(note, noteHeading, data);\n }\n }\n } else if (item.action == 'delete_note') {\n if (editingNote == data.id) {\n Notification.alert(strings.warning, strings.note_deleted_text);\n stopNoteEdit();\n }\n let note = getNote(data.id);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n\n } else if (item.action == 'add_column') {\n addColumn(data.id, data.name, false, {}, selectHeadingColour());\n } else if (item.action == 'move_column') {\n const board = $('.mod_board');\n data.sortorder.forEach(column => {\n const columnElement = board.find(`.board_column[data-ident='${column}']`);\n columnElement.detach().appendTo(board);\n });\n } else if (item.action == 'update_column') {\n $(\".board_column[data-ident='\" + data.id + \"'] .mod_board_column_name\").html(data.name);\n updateColumnAria(data.id);\n } else if (item.action == 'lock_column') {\n $(\".board_column[data-ident='\" + data.id + \"']\").attr(\"data-locked\", data.locked);\n if (data.locked) {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').addClass('d-none');\n } else {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').removeClass('d-none');\n }\n updateSortable();\n } else if (item.action == 'delete_column') {\n var column = $(\".board_column[data-ident='\" + data.id + \"']\");\n if (editingNote && column.find('.board_note[data-ident=\"' + editingNote + '\"]').length) {\n stopNoteEdit();\n }\n column.remove();\n } else if (item.action == 'rate_note') {\n var note = getNote(data.id);\n note.find('.mod_board_rating').html(data.rating);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n lastHistoryId = item.id;\n }\n\n updateBoard();\n });\n };\n\n /**\n * Trigger a board update.\n *\n * @method updateBoard\n * @param {boolean} instant\n */\n var updateBoard = function(instant) {\n if (instant) {\n processBoardHistory();\n } else if (options.history_refresh > 0) {\n if (reloadTimer) {\n stopUpdating();\n }\n reloadTimer = setTimeout(processBoardHistory, options.history_refresh * 1000);\n }\n };\n\n /**\n * Stop/prevent the board reload timer from firing.\n *\n * @method stopUpdating\n */\n var stopUpdating = function() {\n clearTimeout(reloadTimer);\n reloadTimer = null;\n };\n\n /**\n * Sort a set of notes.\n *\n * @sortNotes\n * @param {string} content\n * @param {boolean} toggle\n */\n var sortNotes = function(content, toggle) {\n var sortCol = $(content).parent().find('.mod_board_column_sort'),\n direction = $(content).data('sort');\n if (!direction) {\n if (sortby == SORTBY_RATING) {\n direction = 'desc';\n } else {\n direction = 'asc';\n }\n }\n if (toggle) {\n direction = direction == 'asc' ? 'desc' : 'asc';\n }\n\n if (direction == 'asc') {\n sortCol.removeClass('fa-angle-down');\n sortCol.addClass('fa-angle-up');\n } else {\n sortCol.removeClass('fa-angle-up');\n sortCol.addClass('fa-angle-down');\n }\n $(content).data('sort', direction);\n\n var desc,\n asc;\n if (sortby == SORTBY_DATE) {\n desc = function(a, b) {\n return $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_RATING) {\n desc = function(a, b) {\n return $(b).find('.mod_board_rating').text() - $(a).find('.mod_board_rating').text() ||\n $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).find('.mod_board_rating').text() - $(b).find('.mod_board_rating').text() ||\n $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_NONE) {\n let sortElements = (a, b) => {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n $('> .board_note', $(content)).sort(sortElements).appendTo($(content));\n return;\n }\n\n $('> .board_note', $(content)).sort(direction === 'asc' ? asc : desc).appendTo($(content));\n\n };\n\n /**\n * Update sorting of sortable content.\n *\n * @method updateSortable\n */\n var updateSortable = function() {\n let fromColumnID;\n $(\".board_column[data-locked='false'] .board_column_content\").sortable({\n connectWith: \".board_column[data-locked='false'] .board_column_content\",\n cancel: \".mod_board_nosort\",\n handle: \".move_note\",\n start: function(_, ui) {\n fromColumnID = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n var note = $(ui.item),\n tocolumn = note.closest('.board_column'),\n elem = $(this),\n noteid = note.data('ident'),\n columnid = tocolumn.data('ident');\n let columnElements = tocolumn.find('.board_column_content').children();\n let sortorder = columnElements.index($(`.board_note[data-ident=${noteid}]`));\n let payload = {\n id: noteid,\n columnid: columnid,\n ownerid: ownerId,\n sortorder: sortorder\n };\n moveNote(fromColumnID, payload, elem);\n }\n });\n };\n\n /**\n * Move a note to a new position / column.\n *\n * @param {Int} fromColumnID The column the note is being moved from.\n * @param {Object} payload The payload to send to the server.\n * @param {Domnode} elem The element clicked to trigger the move.\n */\n const moveNote = (fromColumnID, payload, elem) => {\n updateSortOrders(fromColumnID, payload.columnid, payload.id, payload.sortorder);\n\n serviceCall('move_note', payload, (result) => {\n if (result.status) {\n lastHistoryId = result.historyid;\n updateNoteAria(payload.id);\n updateBoard();\n sortNotes($(`.board_column[data-ident=${payload.columnid}] .board_column_content`));\n } else {\n if (elem) {\n elem.sortable('cancel');\n }\n }\n });\n };\n\n /**\n * Enable column sorting\n */\n const columnSorting = () => {\n let movingColumnId;\n $(\".mod_board\").sortable({\n connectWith: \".mod_board\",\n axis: \"x\",\n containment: \".mod_board_wrapper\",\n cancel: \".mod_board_nosort\",\n handle: \".mod_column_move\",\n start: function(_, ui) {\n movingColumnId = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n let column = $(ui.item);\n let columns = $(\".mod_board\").find('.board_column');\n let sortorder = columns.index(column);\n let payload = {\n id: movingColumnId,\n sortorder: sortorder\n };\n moveColumn(payload);\n }\n });\n };\n\n /**\n * Move a column to a new position.\n *\n * @param {Object} payload The payload to send to the server.\n */\n const moveColumn = (payload) => {\n serviceCall('move_column', payload, false);\n };\n\n /**\n * Updates the inline data attributes necessary for rendering the lists\n * in the correct sort order. Note: the data attribute values updated by\n * jQuery are not reflected in DOM inspection but are still set.\n * @param {number} fromColumnID The column ID of the column to sort.\n * @param {number} toColumnID The column ID of the column to sort.\n * @param {number} noteID The note ID that was moved.\n * @param {number} newSortOrder The new position of the note sort order.\n */\n const updateSortOrders = (fromColumnID, toColumnID, noteID, newSortOrder) => {\n let toColumn = $(`.board_column[data-ident=${toColumnID}] .board_column_content`);\n let movedNote = $(`.board_note[data-ident=${noteID}]`);\n let oldSortOrder = movedNote.data('sortorder');\n // Check whether it is the same column and then increment or decrement notes above or below\n // then set sortorder according to whether the sortorder has moved up or down.\n let toChildren = toColumn.children();\n if (fromColumnID == toColumnID) {\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (oldSortOrder < newSortOrder) {\n if (sortOrder <= newSortOrder && sortOrder >= oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n } else if (oldSortOrder > newSortOrder) {\n if (sortOrder >= newSortOrder && sortOrder <= oldSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n }\n });\n } else {\n let fromColumn = $(`.board_column[data-ident=${fromColumnID}] .board_column_content`);\n let fromChildren = fromColumn.children();\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder >= newSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n });\n fromChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder > oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n });\n }\n movedNote.data('sortorder', newSortOrder);\n };\n\n /**\n * Get the body fragment for the modal form.\n *\n * @param {number} noteid\n * @param {number} columnid\n * @param {number} ownerId\n * @returns {Deferred|*}\n */\n var getBody = function(noteid, columnid, ownerId) {\n // Get the content of the modal.\n var params = {noteid: noteid, columnid: columnid, ownerid: ownerId};\n return Fragment.loadFragment('mod_board', 'note_form', contextid, params);\n };\n\n /**\n * Setup the aria labels for the modal.\n *\n * @param {object} note\n * @param {object} modal\n */\n var updateModalAria = function(note, modal) {\n let columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text(),\n addYoutube,\n addImage,\n addLink,\n postButton,\n cancelButton,\n modalRoot = modal.getRoot();\n\n if (note.data('ident')) {\n // Is a note update.\n var noteIdentifier = textIdentifierForNote(note);\n\n postButton = strings.aria_postedit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n cancelButton = strings.aria_canceledit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n addYoutube = strings.aria_addmedia.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addImage = strings.aria_addmedia.replace('{type}', strings.option_image).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addLink = strings.aria_addmedia.replace('{type}', strings.option_link).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n } else {\n // Note is new.\n postButton = strings.aria_postnew.replace('{column}', columnIdentifier);\n cancelButton = strings.aria_cancelnew.replace('{column}', columnIdentifier);\n addYoutube = strings.aria_addmedianew.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier);\n addImage = strings.aria_addmedianew.replace('{type}', strings.option_image).replace('{column}', columnIdentifier);\n addLink = strings.aria_addmedianew.replace('{type}', strings.option_link).replace('{column}', columnIdentifier);\n }\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('aria-label', addYoutube);\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('title', addYoutube);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('aria-label', addImage);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('title', addImage);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('aria-label', addLink);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('title', addLink);\n }\n\n let button = modalRoot.find(modal.getActionSelector('save'));\n if (button) {\n button.attr('aria-label', postButton);\n }\n button = modalRoot.find(modal.getActionSelector('cancel'));\n if (button) {\n button.attr('aria-label', cancelButton);\n }\n };\n\n /**\n * Displays the modal form to edit a note.\n *\n * @param {object} note\n */\n var showModalForm = function(note) {\n let noteId = 0,\n columnId = note.data('column'),\n column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n title;\n\n if (note.data('ident')) {\n noteId = note.data('ident');\n title = strings.modal_title_edit.replace('{column}', columnIdentifier);\n } else {\n title = strings.modal_title_new.replace('{column}', columnIdentifier);\n }\n\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: getBody(noteId, columnId, ownerId),\n large: true,\n removeOnClose: true\n }).then(function(modal) {\n // Use the body promise so we know body content is loaded.\n modal.getBodyPromise().then(function () {\n let saveInProgress = false;\n editModal = modal;\n modal.setLarge();\n modal.setSaveButtonText(strings.post_button_text);\n modal.setButtonText('cancel', strings.cancel_button_text);\n\n modal.getRoot().on(ModalEvents.hidden, function () {\n stopNoteEdit();\n if (!note.data('ident')) {\n note.remove();\n }\n });\n\n modal.getRoot().on(ModalEvents.save, function (e) {\n e.preventDefault();\n modal.getRoot().find('form').submit();\n });\n\n var changeEvent = document.createEvent('HTMLEvents');\n changeEvent.initEvent('change', true, true);\n\n modal.getRoot().on('submit', 'form', function (e) {\n e.preventDefault();\n\n // Prevent multiple form submissions from being sent.\n if (saveInProgress) {\n return;\n }\n saveInProgress = true;\n\n // First, make sure the native html5 validity checks are run.\n let valid = modal.getRoot().find('form').get(0).reportValidity();\n if (!valid) {\n saveInProgress = false;\n return;\n }\n\n // Prompt all inputs to run their validation functions.\n // Normally this would happen when the form is submitted, but\n // since we aren't submitting the form normally we need to run client side\n // validation.\n modal.getRoot().find(':input').each(function (index, element) {\n element.dispatchEvent(changeEvent);\n });\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n var invalid = $.merge(\n modal.getRoot().find('[aria-invalid=\"true\"]'),\n modal.getRoot().find('.error'),\n modal.getRoot().find(':invalid')\n );\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n saveInProgress = false;\n return;\n }\n\n var formData = JSON.stringify(modal.getRoot().find('form').serialize());\n serviceCall('submit_form', {contextid: contextid, jsonformdata: formData}, function (result) {\n if (result.status) {\n if (result.action == 'insert') {\n // Added a new note.\n lastHistoryId = result.historyid;\n note.remove();\n addNote(columnId, result.note.id, result.note.heading, result.note.content,\n {type: result.note.type, info: result.note.info, url: result.note.url},\n {id: result.note.userid}, result.note.timecreated, result.note.rating);\n sortNotes($('.board_column[data-ident=' + columnId + '] .board_column_content'));\n updateNoteAria(result.note.id);\n } else {\n // Updated existing note.\n lastHistoryId = result.historyid;\n getNoteTextForNote(note).html(result.note.content);\n getNoteHeadingForNote(note).html(result.note.heading);\n updateNoteAria(result.note.id);\n setAttachment(note, {\n type: result.note.type,\n info: result.note.info, url: result.note.url\n });\n }\n stopNoteEdit();\n\n // Clear the form changed checker.\n Y.use('moodle-core-formchangechecker', function() {\n M.core_formchangechecker.reset_form_dirty_state();\n });\n\n modal.destroy();\n } else {\n modal.destroy();\n }\n });\n\n });\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n // First hide the select menu.\n modal.getRoot().find('#fitem_id_mediatype').hide();\n\n let mediaSelect = modal.getRoot().find('#fitem_id_mediatype select'),\n ytButton = modal.getRoot().find('.mod_board_attachment_button.youtube_button'),\n pictureButton = modal.getRoot().find('.mod_board_attachment_button.image_button'),\n linkButton = modal.getRoot().find('.mod_board_attachment_button.link_button'),\n updateMediaButtons = function() {\n ytButton.removeClass('selected');\n pictureButton.removeClass('selected');\n linkButton.removeClass('selected');\n switch (mediaSelect.val()) {\n case (\"1\"):\n ytButton.addClass('selected');\n break;\n case (\"2\"):\n pictureButton.addClass('selected');\n break;\n case (\"3\"):\n linkButton.addClass('selected');\n break;\n }\n };\n\n updateMediaButtons();\n handleAction(ytButton, function() {\n if (mediaSelect.val() === \"1\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(1);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(pictureButton, function() {\n if (mediaSelect.val() === \"2\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(2);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(linkButton, function() {\n if (mediaSelect.val() === \"3\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(3);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n } else {\n modal.getRoot().find('#fitem_id_mediabuttons').hide();\n }\n\n updateModalAria(note, modal);\n modal.show();\n\n return modal;\n }).catch(Notification.exception);\n return modal;\n }).catch(Notification.exception);\n };\n\n /**\n * Show the note in a modal\n * @param {Int} ident The note id\n * @param {Object} notecontent The note content\n */\n var fullScreenNote = (ident, notecontent) => {\n const heading = getNoteHeadingForNote(notecontent).html();\n const modalBody = $(document.createElement('div'));\n modalBody.addClass('mod_board_note_content');\n const text = getNoteTextForNote(notecontent);\n if (text) {\n modalBody.append(text.clone());\n }\n const preview = getNotePreviewForNote(notecontent);\n if (preview) {\n modalBody.append(preview.clone());\n }\n\n // Adds the comments to a note.\n const commentArea = $(document.createElement('div'));\n commentArea.attr('data-region', 'comment-area');\n modalBody.append(commentArea);\n Comments.fetchFor(ident, commentArea);\n\n ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: heading,\n body: modalBody,\n }).then(function(modal) {\n modal.setLarge();\n modal.show();\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function () {\n // Destroy when hidden.\n modal.destroy();\n });\n return modal;\n }, this).catch(Notification.exception);\n };\n\n /**\n * Initialize board.\n *\n * @method init\n */\n var init = function() {\n serviceCall('get_board', {id: board.id, ownerid: ownerId}, function(columns) {\n // Init\n if (columns) {\n for (var index in columns) {\n addColumn(\n columns[index].id,\n columns[index].name,\n columns[index].locked,\n columns[index].notes || {},\n options.colours[columns[index].id % options.colours.length]\n );\n }\n }\n\n if (isEditor) {\n addNewColumnButton();\n }\n\n lastHistoryId = board.historyid;\n\n if (isEditor) {\n updateSortable();\n columnSorting();\n }\n\n updateBoard();\n });\n };\n\n // Get strings\n var stringsInfo = [];\n for (var string in strings) {\n stringsInfo.push({key: string, component: 'mod_board'});\n }\n\n $.when(getStrings(stringsInfo)).done(function(results) {\n var index = 0;\n for (string in strings) {\n strings[string] = results[index++];\n }\n\n init();\n });\n}\n"],"names":["settings","strings","default_column_heading","post_button_text","cancel_button_text","remove_note_title","remove_note_text","remove_column_title","note_changed_title","note_changed_text","note_deleted_text","rate_note_title","rate_note_text","rate_remove_note_text","Ok","delete","Cancel","warning","modal_title_new","modal_title_edit","option_youtube","option_image","option_link","aria_newcolumn","aria_newpost","aria_deletecolumn","aria_movecolumn","aria_deletepost","aria_movepost","aria_editpost","aria_addmedia","aria_addmedianew","aria_deleteattachment","aria_postedit","aria_canceledit","aria_postnew","aria_cancelnew","aria_ratepost","invalid_file_extension","invalid_file_size_min","invalid_file_size_max","invalid_youtube_url","options","JSON","parse","board","contextid","reloadTimer","lastHistoryId","isEditor","usersCanEdit","userId","parseInt","userFullname","ownerId","mediaSelection","mediaselection","editingNote","isReadOnlyBoard","readonly","showauthorofnote","allowshowauthorofnoteonboard","ratingenabled","sortby","editModal","enableblanktarget","serviceCall","method","args","callback","failcallback","stopUpdating","call","methodname","done","data","fail","error","exception","_serviceCall","apply","arguments","updateBoard","getNote","ident","getNoteTextForNote","note","find","getNoteHeadingForNote","getNoteBorderForNote","getNoteAttachmentsForNote","textIdentifierForNote","noteText","html","noteHeading","noteAttachment","attachmentDataForNote","length","replace","split","slice","join","info","updateNoteAria","noteId","columnIdentifier","closest","text","noteIdentifier","deleteNoteString","attr","moveNoteString","editNoteString","updateColumnAria","columnId","column","newNoteString","moveColumnString","deleteColumnString","each","index","stopNoteEdit","noteBorder","show","hide","remove","sortAfterDelete","columnID","sortorder","getColumn","children","filter","_","element","so","setAttachment","attachment","type","attType","val","decodeText","url","attachmentInfo","attachmentUrl","attachmentFile","prop","attachmentTypeToString","FileReader","attachmentTypeChanged","previewAttachment","filename","filecontents","encodeText","fileElem","elem","removeClass","addClass","blanktarget","videoID","match","undefined","getEmbedUrl","addNote","columnid","heading","content","owner","rating","ismynote","id","iseditable","pendingNote","notecontent","notecontrols","noteAuthorusername","noteAriaText","attachmentPreview","fullname","append","columnContent","beginEdit","showModalForm","startNoteEdit","rateElement","handleAction","result","canrate","rateRemoveText","hasrated","confirm","status","historyid","sortNotes","then","rateModal","getRoot","on","ModalEvents","hidden","rateNote","removeElement","deleteNote","moveElement","init","moveNote","editElement","updateSortable","fullScreenNote","lastOne","last","insertAfter","prepend","addColumn","name","locked","notes","colour","headerStyle","nameCache","columnHeader","columnSort","columnName","columnNewContent","hideheaders","lockIcon","lockElement","lockstring","str","lockColumn","moveColumn","getColumnName","callBeforeOnKeyEditing","is","Error","e","isAriaTriggerKey","keyCode","preventDefault","editable","handleEditableAction","toggleFontSize","closeOnEnter","newNoteButton","noteicon","timecreated","userid","columnSorting","selectHeadingColour","colCount","colourCount","colours","updateNote","processBoardHistory","ownerid","since","boardhistory","item","boardid","action","formModal","historyData","alert","forEach","detach","appendTo","instant","history_refresh","setTimeout","clearTimeout","toggle","desc","asc","sortCol","parent","direction","a","b","sortElements","sort","fromColumnID","sortable","connectWith","cancel","handle","start","ui","stop","tocolumn","this","noteid","payload","updateSortOrders","movingColumnId","axis","containment","toColumnID","noteID","newSortOrder","toColumn","movedNote","oldSortOrder","toChildren","sortOrder","fromChildren","getBody","params","Fragment","loadFragment","title","create","ModalFactory","types","SAVE_CANCEL","body","large","removeOnClose","modal","getBodyPromise","saveInProgress","setLarge","setSaveButtonText","setButtonText","save","submit","changeEvent","document","createEvent","initEvent","get","reportValidity","dispatchEvent","invalid","$","merge","first","focus","formData","stringify","serialize","jsonformdata","Y","use","M","core_formchangechecker","reset_form_dirty_state","destroy","mediaSelect","ytButton","pictureButton","linkButton","updateMediaButtons","addYoutube","addImage","addLink","postButton","cancelButton","modalRoot","button","getActionSelector","updateModalAria","catch","Notification","modalBody","createElement","clone","preview","commentArea","fetchFor","CANCEL","columns","newBusy","columnicon","stringsInfo","string","push","key","component","when","results","rawText","encodedText"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/board.js b/amd/src/board.js index c43b3ce..739f66c 100755 --- a/amd/src/board.js +++ b/amd/src/board.js @@ -218,13 +218,13 @@ export default function(settings) { isEditor = options.isEditor || false, usersCanEdit = options.usersCanEdit, userId = parseInt(options.userId) || -1, - userFirstname = options.firstname, - userLastname = options.lastname, + userFullname = options.userFullname, ownerId = parseInt(options.ownerId), mediaSelection = options.mediaselection || MEDIA_SELECTION_BUTTONS, editingNote = 0, isReadOnlyBoard = options.readonly || false, showauthorofnote = options.showauthorofnote || false, + allowshowauthorofnoteonboard = options.allowshowauthorofnoteonboard || false, ratingenabled = options.ratingenabled, sortby = options.sortby || SORTBY_DATE, editModal = null, @@ -756,7 +756,7 @@ export default function(settings) { * @param {string} heading * @param {string} content * @param {object} attachment - * @param {object} owner + * @param {object} owner the owner of the note containing the userid as id and the owner fullname * @param {number} sortorder * @param {string} rating */ @@ -804,25 +804,19 @@ export default function(settings) { noteAriaText = $(''), attachmentPreview = $('
'); - if (showauthorofnote) { - let firstname = ''; - let lastname = ''; + if (allowshowauthorofnoteonboard == true && showauthorofnote == true) { + let fullname = ''; if (ismynote) { // Use the Name of the user itself. We do not need to get this information from somewhere else. - firstname = userFirstname; - lastname = userLastname; + fullname = userFullname; } else { - firstname = owner.firstname; - lastname = owner.lastname; + fullname = owner.fullname; } noteAuthorusername = '
' + - ' ' + - '' + - firstname + - '' + - '' + - lastname + + ' ' + + '' + + fullname + '' + '
' ; } @@ -1047,7 +1041,7 @@ export default function(settings) { newNoteButton.addClass('d-none'); } handleAction(columnNewContent.find('.newnote'), function() { - // We do not need to add firstname and lasname because we use ismynote and actual board user. + // We do not need to add fullname to the owner because we use ismynote and the fullname of the actual board user. addNote(ident, 0, null, null, null, {id: userId}, 0, 0); }); } @@ -1065,7 +1059,7 @@ export default function(settings) { addNote(ident, notes[index].id, notes[index].heading, notes[index].content, {type: notes[index].type, info: notes[index].info, url: notes[index].url}, - {id: notes[index].userid, firstname: notes[index].firstname, lastname: notes[index].lastname}, + {id: notes[index].userid, fullname: notes[index].fullname}, sortorder, notes[index].rating); } } diff --git a/classes/board.php b/classes/board.php index 4feeda8..24e7cf1 100644 --- a/classes/board.php +++ b/classes/board.php @@ -16,8 +16,12 @@ namespace mod_board; +use tool_brickfield\local\areas\core_course\fullname; +use core_user; + /** * The main board class functions. + * * @package mod_board * @author Jay Churchward * @copyright 2021 Brickfield Education Labs @@ -101,8 +105,7 @@ public static function get_configuration($id, $ownerid) { 'isEditor' => self::board_is_editor($board->id), 'usersCanEdit' => self::board_users_can_edit($board->id), 'userId' => $USER->id, - 'firstname' => $USER->firstname, - 'lastname' => $USER->lastname, + 'userFullname' => fullname($USER), 'ownerId' => $ownerid, 'readonly' => (self::board_readonly($board->id) || !self::can_post($board->id, $USER->id, $ownerid)), 'columnicon' => $config->new_column_icon, @@ -115,6 +118,7 @@ public static function get_configuration($id, $ownerid) { 'size_min' => self::ACCEPTED_FILE_MIN_SIZE, 'size_max' => self::ACCEPTED_FILE_MAX_SIZE ], + 'allowshowauthorofnoteonboard' => isset($config->allowshowauthorofnoteonboard) ? $config->allowshowauthorofnoteonboard : false, 'showauthorofnote' => self::board_show_authorofnote($board->id), 'ratingenabled' => self::board_rating_enabled($board->id), 'hideheaders' => self::board_hide_headers($board->id), @@ -377,14 +381,14 @@ public static function board_get(int $boardid, int $ownerid = 0): array { 'id, userid, heading, content, type, info, url, timecreated, sortorder'); // Add the name of the author of a note to the note-object. + $config = get_config('mod_board'); + $allowshowauthorofnoteonboard = isset($config->allowshowauthorofnoteonboard) ? $config->allowshowauthorofnoteonboard : false; foreach ($column->notes as $colid => $note) { - if (self::board_show_authorofnote($board->id)) { - $authorofnote = static::get_authorofnote($note->userid); - $note->firstname = $authorofnote['firstname']; - $note->lastname = $authorofnote['lastname']; + if ($allowshowauthorofnoteonboard && self::board_show_authorofnote($board->id)) { + $user = core_user::get_user($note->userid); + $note->fullname = fullname($user);; } else { - $note->firstname = ''; - $note->lastname = ''; + $note->fullname = ''; } } @@ -396,22 +400,7 @@ public static function board_get(int $boardid, int $ownerid = 0): array { static::clear_history(); return $columns; } - - /** - * Gets the author/user (including firstname and lastname) of a note. - * - * @param int $userid The userid of the author of a note. - * @return array - */ - public static function get_authorofnote($userid): array { - global $DB; - $user = $DB->get_record('user', ['id' => $userid], 'firstname, lastname'); - $authorofnote = []; - $authorofnote['firstname'] = $user->firstname; - $authorofnote['lastname'] = $user->lastname; - return $authorofnote; - } - + /** * Retrieves the boards history. * diff --git a/external.php b/external.php index a17496b..2f8efd6 100755 --- a/external.php +++ b/external.php @@ -129,8 +129,7 @@ public static function get_board_returns(): external_multiple_structure { array( 'id' => new external_value(PARAM_INT, 'post id'), 'userid' => new external_value(PARAM_INT, 'user id'), - 'firstname' => new external_value(PARAM_TEXT, 'user firstname'), - 'lastname' => new external_value(PARAM_TEXT, 'user lastname'), + 'fullname' => new external_value(PARAM_TEXT, 'user fullname'), 'heading' => new external_value(PARAM_TEXT, 'post heading'), 'content' => new external_value(PARAM_RAW, 'post content'), 'type' => new external_value(PARAM_INT, 'type'), diff --git a/scss/styles.scss b/scss/styles.scss index 589993e..fbce632 100644 --- a/scss/styles.scss +++ b/scss/styles.scss @@ -147,10 +147,7 @@ } .mod_board_note_author { - .mod_board_note_author_firstname { - color: #12129a; - } - .mod_board_note_author_lastname { + .mod_board_note_author_fullname { margin-left: 3px; color: #12129a; } diff --git a/styles.css b/styles.css index a8dae86..766e26e 100755 --- a/styles.css +++ b/styles.css @@ -169,11 +169,7 @@ max-width: initial; } -.mod_board .mod_board_note_content .mod_board_note_author .mod_board_note_author_firstname { - color: #12129a; -} - -.mod_board .mod_board_note_content .mod_board_note_author .mod_board_note_author_lastname { +.mod_board .mod_board_note_content .mod_board_note_author .mod_board_note_author_fullname { margin-left: 3px; color: #12129a; } diff --git a/view.php b/view.php index a6e1c99..96ef39b 100755 --- a/view.php +++ b/view.php @@ -100,6 +100,17 @@ echo html_writer::tag('div', get_string('blanktargetenabled', 'mod_board'), ['class' => 'small']); } + +$config = get_config('mod_board'); +$allowshowauthorofnoteonboard = isset($config->allowshowauthorofnoteonboard) ? $config->allowshowauthorofnoteonboard : false; + +if ($allowshowauthorofnoteonboard) { + echo html_writer::tag('div', 'In diesem Moodle ist die Anzeige von Autoren der Notizen erlaubt.', ['class' => 'small']); +} else { + echo html_writer::tag('div', 'In diesem Moodle ist die Anzeige von Autoren der Notizen NICHT aktiviert.', ['class' => 'small']); +} + + if ($board->showauthorofnote) { echo html_writer::tag('div', get_string('showauthorofnoteinfoenabled', 'mod_board'), ['class' => 'small']); } else { From f636f63f698a070ee10882c0d4e3a303afa80258 Mon Sep 17 00:00:00 2001 From: Andreas Schenkel Date: Wed, 13 Dec 2023 09:30:31 +0100 Subject: [PATCH 3/6] some layout and langstring changes --- classes/board.php | 2 +- lang/en/board.php | 3 +++ view.php | 33 ++++++++++++++++----------------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/classes/board.php b/classes/board.php index 24e7cf1..613f452 100644 --- a/classes/board.php +++ b/classes/board.php @@ -400,7 +400,7 @@ public static function board_get(int $boardid, int $ownerid = 0): array { static::clear_history(); return $columns; } - + /** * Retrieves the boards history. * diff --git a/lang/en/board.php b/lang/en/board.php index 7374eed..51ed7c2 100755 --- a/lang/en/board.php +++ b/lang/en/board.php @@ -255,3 +255,6 @@ $string['adminsetting:allowshowauthorofnoteonboard'] = 'Allow to activate to show author of note on boards'; $string['adminsetting:allowshowauthorofnoteonboard_desc'] = 'If activated the board can be configured to show the author of a note on the board or the author can be hidden to students (Teacher can see owner of note by using the export).'; + +$string['allowshowauthorofnoteonboardenabled'] = 'This moodle DOES support to show author of notes.'; +$string['allowshowauthorofnoteonboarddisabled'] = 'This moodle does NOT support to show author of notes.'; diff --git a/view.php b/view.php index 96ef39b..9535760 100755 --- a/view.php +++ b/view.php @@ -100,23 +100,6 @@ echo html_writer::tag('div', get_string('blanktargetenabled', 'mod_board'), ['class' => 'small']); } - -$config = get_config('mod_board'); -$allowshowauthorofnoteonboard = isset($config->allowshowauthorofnoteonboard) ? $config->allowshowauthorofnoteonboard : false; - -if ($allowshowauthorofnoteonboard) { - echo html_writer::tag('div', 'In diesem Moodle ist die Anzeige von Autoren der Notizen erlaubt.', ['class' => 'small']); -} else { - echo html_writer::tag('div', 'In diesem Moodle ist die Anzeige von Autoren der Notizen NICHT aktiviert.', ['class' => 'small']); -} - - -if ($board->showauthorofnote) { - echo html_writer::tag('div', get_string('showauthorofnoteinfoenabled', 'mod_board'), ['class' => 'small']); -} else { - echo html_writer::tag('div', get_string('showauthorofnoteinfodisabled', 'mod_board'), ['class' => 'small']); -} - echo $OUTPUT->box_start('mod_introbox', 'group_menu'); echo groups_print_activity_menu($cm, $pageurl, true); echo $OUTPUT->box_end(); @@ -159,6 +142,22 @@ $extrabackground = "background:url({$url}) no-repeat center center; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover; background-size: cover;"; } + + $config = get_config('mod_board'); + $allowshowauthorofnoteonboard = isset($config->allowshowauthorofnoteonboard) ? $config->allowshowauthorofnoteonboard : false; + + if ($allowshowauthorofnoteonboard) { + echo html_writer::tag('div', get_string('allowshowauthorofnoteonboardenabled', 'mod_board'), ['class' => 'mod_board_allowshowauthorofnoteonboardenabled']); + } else { + echo html_writer::tag('div', get_string('allowshowauthorofnoteonboarddisabled', 'mod_board'), ['class' => 'mod_board_allowshowauthorofnoteonboarddisabled']); + } + + if ($board->showauthorofnote) { + echo html_writer::tag('div', get_string('showauthorofnoteinfoenabled', 'mod_board'), ['class' => 'mod_board_showauthorofnoteinfoenabled']); + } else { + echo html_writer::tag('div', get_string('showauthorofnoteinfodisabled', 'mod_board'), ['class' => 'mod_board_showauthorofnoteinfodisabled']); + } + echo '
'; echo '
'; if (has_capability('mod/board:manageboard', $context)) { From 9fbcc691b6bc1fe4680fa7d550ad60bade52382a Mon Sep 17 00:00:00 2001 From: Andreas Schenkel Date: Wed, 13 Dec 2023 16:58:55 +0100 Subject: [PATCH 4/6] refactor adding fullname to note --- classes/board.php | 12 +++++++++--- external.php | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/classes/board.php b/classes/board.php index 613f452..7976e90 100644 --- a/classes/board.php +++ b/classes/board.php @@ -77,6 +77,8 @@ class board { /** @var int Value for the singleusermode setting in public mode*/ const SINGLEUSER_PUBLIC = 2; + static $alluserids = []; + /** * Retrieves the course module for the board * @@ -380,13 +382,17 @@ public static function board_get(int $boardid, int $ownerid = 0): array { $column->notes = $DB->get_records('board_notes', $params, 'sortorder', 'id, userid, heading, content, type, info, url, timecreated, sortorder'); - // Add the name of the author of a note to the note-object. $config = get_config('mod_board'); $allowshowauthorofnoteonboard = isset($config->allowshowauthorofnoteonboard) ? $config->allowshowauthorofnoteonboard : false; + // Add fullname of author to each note if author of should be visible. foreach ($column->notes as $colid => $note) { if ($allowshowauthorofnoteonboard && self::board_show_authorofnote($board->id)) { - $user = core_user::get_user($note->userid); - $note->fullname = fullname($user);; + // Only add missing userids and fullnames to reduce calls of get_user(). + if (!self::$alluserids[$note->userid]) { + $user = core_user::get_user($note->userid); + self::$alluserids[$note->userid] = fullname($user); + } + $note->fullname =self::$alluserids[$note->userid]; } else { $note->fullname = ''; } diff --git a/external.php b/external.php index 2f8efd6..a2664fe 100755 --- a/external.php +++ b/external.php @@ -129,7 +129,7 @@ public static function get_board_returns(): external_multiple_structure { array( 'id' => new external_value(PARAM_INT, 'post id'), 'userid' => new external_value(PARAM_INT, 'user id'), - 'fullname' => new external_value(PARAM_TEXT, 'user fullname'), + 'fullname' => new external_value(PARAM_TEXT, 'user fullname', VALUE_DEFAULT, ''), 'heading' => new external_value(PARAM_TEXT, 'post heading'), 'content' => new external_value(PARAM_RAW, 'post content'), 'type' => new external_value(PARAM_INT, 'type'), From 331e1e156bc867e457f994a08542cf4d44830cbc Mon Sep 17 00:00:00 2001 From: Andreas Schenkel Date: Wed, 13 Dec 2023 17:11:00 +0100 Subject: [PATCH 5/6] refactor information at top of board about the setting of show author of board --- view.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/view.php b/view.php index 9535760..c033dad 100755 --- a/view.php +++ b/view.php @@ -146,16 +146,12 @@ $config = get_config('mod_board'); $allowshowauthorofnoteonboard = isset($config->allowshowauthorofnoteonboard) ? $config->allowshowauthorofnoteonboard : false; - if ($allowshowauthorofnoteonboard) { - echo html_writer::tag('div', get_string('allowshowauthorofnoteonboardenabled', 'mod_board'), ['class' => 'mod_board_allowshowauthorofnoteonboardenabled']); - } else { - echo html_writer::tag('div', get_string('allowshowauthorofnoteonboarddisabled', 'mod_board'), ['class' => 'mod_board_allowshowauthorofnoteonboarddisabled']); - } - - if ($board->showauthorofnote) { - echo html_writer::tag('div', get_string('showauthorofnoteinfoenabled', 'mod_board'), ['class' => 'mod_board_showauthorofnoteinfoenabled']); - } else { - echo html_writer::tag('div', get_string('showauthorofnoteinfodisabled', 'mod_board'), ['class' => 'mod_board_showauthorofnoteinfodisabled']); + if ($allowshowauthorofnoteonboard ) { + if ($board->showauthorofnote) { + echo html_writer::tag('div', get_string('showauthorofnoteinfoenabled', 'mod_board'), ['class' => 'mod_board_showauthorofnoteinfoenabled']); + } else { + echo html_writer::tag('div', get_string('showauthorofnoteinfodisabled', 'mod_board'), ['class' => 'mod_board_showauthorofnoteinfodisabled']); + } } echo '
'; From 610a6268b5d0716ba78140738303ced284907741 Mon Sep 17 00:00:00 2001 From: Andreas Schenkel Date: Thu, 14 Dec 2023 14:10:19 +0100 Subject: [PATCH 6/6] WIP: add fullname if note is added or updated on a board after adding or updating in an other browser by an other user --- amd/build/board.min.js | 2 +- amd/build/board.min.js.map | 2 +- amd/src/board.js | 4 +++- classes/board.php | 18 +++++++++++++++--- external.php | 1 + 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/amd/build/board.min.js b/amd/build/board.min.js index 22075a9..33a36c1 100755 --- a/amd/build/board.min.js +++ b/amd/build/board.min.js @@ -5,6 +5,6 @@ define("mod_board/board",["exports","jquery","core/str","core/ajax","core/modal_ * @author Karen Holland * @copyrigt 2021 Brickfield Education Labs * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=function(settings){var strings={default_column_heading:"",post_button_text:"",cancel_button_text:"",remove_note_title:"",remove_note_text:"",remove_column_title:"",note_changed_title:"",note_changed_text:"",note_deleted_text:"",rate_note_title:"",rate_note_text:"",rate_remove_note_text:"",Ok:"",delete:"",Cancel:"",warning:"",modal_title_new:"",modal_title_edit:"",option_youtube:"",option_image:"",option_link:"",aria_newcolumn:"",aria_newpost:"",aria_deletecolumn:"",aria_movecolumn:"",aria_deletepost:"",aria_movepost:"",aria_editpost:"",aria_addmedia:"",aria_addmedianew:"",aria_deleteattachment:"",aria_postedit:"",aria_canceledit:"",aria_postnew:"",aria_cancelnew:"",aria_ratepost:"",invalid_file_extension:"",invalid_file_size_min:"",invalid_file_size_max:"",invalid_youtube_url:""},options=JSON.parse(settings.settings)||{},board=options.board||{},contextid=options.contextid;var reloadTimer=null,lastHistoryId=null,isEditor=options.isEditor||!1,usersCanEdit=options.usersCanEdit,userId=parseInt(options.userId)||-1,userFullname=options.userFullname,ownerId=parseInt(options.ownerId),mediaSelection=options.mediaselection||1,editingNote=0,isReadOnlyBoard=options.readonly||!1,showauthorofnote=options.showauthorofnote||!1,allowshowauthorofnoteonboard=options.allowshowauthorofnoteonboard||!1,ratingenabled=options.ratingenabled,sortby=options.sortby||1,editModal=null,enableblanktarget=1===parseInt(options.enableblanktarget),serviceCall=function(method,args,callback,failcallback){"board_history"!==method&&stopUpdating(),function(method,args,callback,failcallback){_ajax.default.call([{methodname:"mod_board_"+method,args:args,done:function(data){callback(data)},fail:function(error){_notification.default.exception(error),failcallback&&failcallback(error)}}])}(method,args,(function(){callback&&callback.apply(null,arguments),"board_history"!==method&&"get_board"!=method&&updateBoard(!0)}),failcallback)},getNote=function(ident){return(0,_jquery.default)(".board_note[data-ident='"+ident+"']")},getNoteTextForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_text")},getNoteHeadingForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_heading")},getNoteBorderForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_border")},getNoteAttachmentsForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_attachment")},textIdentifierForNote=function(note){var noteText=getNoteTextForNote(note).html(),noteHeading=getNoteHeadingForNote(note).html(),noteAttachment=attachmentDataForNote(note);return noteHeading.length>0?noteHeading:noteText.length>0?noteText.replace(//gi," ").replace(/\n/g," ").split(/\s+/).slice(0,5).join(" "):noteAttachment.info&¬eAttachment.info.length>0?noteAttachment.info:null},updateNoteAria=function(noteId){var note=getNote(noteId),columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text();if(noteId){var noteIdentifier=textIdentifierForNote(note),deleteNoteString=strings.aria_deletepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier);note.find(".delete_note").attr("aria-label",deleteNoteString).attr("title",deleteNoteString);var moveNoteString=strings.aria_movepost.replace("{post}",noteIdentifier);note.find(".move_note").attr("aria-label",moveNoteString).attr("title",moveNoteString);var editNoteString=strings.aria_editpost.replace("{post}",noteIdentifier);note.find(".edit_note").attr("aria-label",editNoteString).attr("title",editNoteString),note.find(".mod_board_rating").attr("aria-label",strings.aria_ratepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)),note.find(".note_ariatext").html(noteIdentifier)}},updateColumnAria=function(columnId){var column=(0,_jquery.default)(".board_column[data-ident="+columnId+"]"),columnIdentifier=column.find(".mod_board_column_name").text(),newNoteString=strings.aria_newpost.replace("{column}",columnIdentifier),moveColumnString=strings.aria_movecolumn.replace("{column}",columnIdentifier),deleteColumnString=strings.aria_deletecolumn.replace("{column}",columnIdentifier);column.find(".newnote").attr("aria-label",newNoteString).attr("title",newNoteString),column.find(".mod_column_move").attr("aria-label",moveColumnString).attr("title",moveColumnString),column.find(".delete_column").attr("aria-label",deleteColumnString).attr("title",deleteColumnString),column.find(".board_note").each((function(index,note){updateNoteAria((0,_jquery.default)(note).data("ident"))}))},stopNoteEdit=function(){if(editingNote){var note=getNote(editingNote);if(note){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())}editingNote=0}else getNote(0).remove()};const sortAfterDelete=(columnID,sortorder)=>{let column=(columnID=>(0,_jquery.default)(".board_column[data-ident='".concat(columnID,"'] .board_column_content")))(columnID);column.children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so-1)}))};var setAttachment=function(note,attachment){var noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment){attachment?attachment.type+="":attachment={type:"0"};var attType=noteAttachment.find(".mod_board_type");attType.val(attachment.type?attachment.type:"0"),attType.val()>"0"&&(noteAttachment.find(".info").val(decodeText(attachment.info)),noteAttachment.find(".url").val(decodeText(attachment.url))),function(note){var noteAttachment=getNoteAttachmentsForNote(note),type=noteAttachment.find(".mod_board_type").val(),attachmentInfo=noteAttachment.find(".info"),attachmentUrl=noteAttachment.find(".url"),attachmentFile=noteAttachment.find(".mod_board_file");type>"0"?(attachmentInfo.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_info"]),attachmentUrl.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_url"]),attachmentInfo.show(),2==type&&FileReader?(attachmentFile.show(),attachmentUrl.hide()):(attachmentFile.hide(),attachmentUrl.show())):(attachmentInfo.hide(),attachmentUrl.hide(),attachmentFile.hide(),attachmentInfo.val(""),attachmentUrl.val(""))}(note)}previewAttachment(note,attachment)},attachmentDataForNote=function(note){var attachment={type:0,info:null,url:null,filename:null,filecontents:null},noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment.length){attachment.type=noteAttachment.find(".mod_board_type").val(),attachment.info=encodeText(noteAttachment.find(".info").val()),attachment.url=encodeText(noteAttachment.find(".url").val());var fileElem=noteAttachment.find(".mod_board_file>input");fileElem.data("filename")&&(attachment.filename=fileElem.data("filename"),attachment.filecontents=fileElem.data("filecontents"))}return attachment.info&&attachment.info.length||attachment.url&&attachment.url.length||attachment.filename||(attachment.type=0),attachment},attachmentTypeToString=function(type){switch(type){case"1":return"youtube";case"2":return"image";case"3":return"link";default:return null}};var previewAttachment=function(note,attachment){var elem=note.find(".mod_board_preview");if(attachment||(attachment=attachmentDataForNote(note)),getNoteTextForNote(note).html().length?elem.removeClass("mod_board_notext"):elem.addClass("mod_board_notext"),elem.removeClass("wrapper_youtube"),elem.removeClass("wrapper_image"),elem.removeClass("wrapper_url"),attachment.filename&&2==parseInt(attachment.type))elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();else if(attachment.url){const blanktarget=enableblanktarget?' target="_blank"':"";switch(parseInt(attachment.type)){case 1:{let url=(url=>{let videoID=url.match(/(\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/);return videoID&&void 0!==videoID[2]&&11===videoID[2].length?"https://www.youtube-nocookie.com/embed/".concat(videoID[2]):null})(attachment.url);null===url?elem.html(strings.invalid_youtube_url):(elem.html(''),elem.addClass("wrapper_youtube").addClass("position-relative")),elem.show()}break;case 2:elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();break;case 3:elem.html('"+(attachment.info||attachment.url)+""),elem.addClass("wrapper_url"),elem.show();break;default:elem.html(""),elem.hide()}}else elem.html(""),elem.hide()},addNote=function(columnid,ident,heading,content,attachment,owner,sortorder,rating){var ismynote=owner.id==userId||!ident,iseditable=isEditor||ismynote&&!isReadOnlyBoard;if(!ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}if(3==sortby){(0,_jquery.default)(".board_column[data-ident='".concat(columnid,"'] .board_column_content")).children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>=parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so+1)}))}var note=(0,_jquery.default)('
');ismynote&¬e.addClass("mod_board_mynote"),iseditable&¬e.addClass("mod_board_editablenote"),ismynote||iseditable||note.addClass("mod_board_nosort");var notecontent=(0,_jquery.default)('
'),notecontrols=(0,_jquery.default)('
'),noteHeading=(0,_jquery.default)('
'+(heading||"")+"
"),noteAuthorusername=(0,_jquery.default)(""),noteBorder=(0,_jquery.default)('
'),noteText=(0,_jquery.default)('
'+(content||"")+"
"),noteAriaText=(0,_jquery.default)(''),attachmentPreview=(0,_jquery.default)('
');if(1==allowshowauthorofnoteonboard&&1==showauthorofnote){let fullname="";fullname=ismynote?userFullname:owner.fullname,noteAuthorusername='
'+fullname+"
"}notecontent.append(noteHeading),notecontent.append(noteAuthorusername),notecontent.append(noteBorder),notecontent.append(noteText),notecontent.append(noteAriaText),notecontent.append(attachmentPreview),note.append(notecontent);var columnContent=(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_content"),beginEdit=()=>{!function(ident){if(editingNote){if(editingNote==ident)return;stopNoteEdit()}if(ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}var note=getNote(ident);note&&(showModalForm(note),ident&&(editingNote=ident))}(ident)};if(ident){if(ratingenabled){note.addClass("mod_board_rateablenote");var rateElement=(0,_jquery.default)('
'.concat(rating,"
"));handleAction(rateElement,(()=>{!function(ident){if(ratingenabled&&!isReadOnlyBoard){var note=getNote(ident),rating=note.find(".mod_board_rating");rating.data("disabled")||(rating.data("disabled",!0),serviceCall("can_rate_note",{id:ident},(function(result){if(result.canrate){const rateRemoveText=result.hasrated?strings.rate_remove_note_text:strings.rate_note_text;_notification.default.confirm(strings.rate_note_title,rateRemoveText,strings.Ok,strings.Cancel,(function(){serviceCall("rate_note",{id:ident},(function(result){result.status&&(lastHistoryId=result.historyid,rating.html(" ".concat(result.rating," ")),2==sortby&&sortNotes(note.closest(".board_column_content"))),rating.data("disabled",!1)}))})).then((function(rateModal){rateModal.getRoot().on(_modal_events.default.hidden,(function(){rating.data("disabled",!1)}))}))}})))}}(ident)})),notecontrols.append(rateElement)}if(iseditable){var removeElement=(0,_jquery.default)('
');if(handleAction(removeElement,(()=>{!function(ident){_notification.default.confirm(strings.remove_note_title,strings.remove_note_text,strings.delete,strings.Cancel,(function(){serviceCall("delete_note",{id:ident},(function(result){if(result.status){lastHistoryId=result.historyid;let note=getNote(ident);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}}))}))}(ident)})),notecontrols.append(removeElement),1==usersCanEdit||isEditor){var moveElement=(0,_jquery.default)('
');notecontrols.append(moveElement),_movenotesdialog.default.init(ownerId,moveNote)}var editElement=(0,_jquery.default)('
');notecontrols.append(editElement),handleAction(editElement,(()=>{beginEdit()})),updateSortable(),setAttachment(note,attachment)}else previewAttachment(note,attachment);note.append(notecontrols),handleAction(notecontent,(()=>fullScreenNote(ident,notecontent))),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide());var lastOne=columnContent.find(".board_note").last();lastOne.length?note.insertAfter(lastOne):columnContent.prepend(note)}else(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_newcontent").append(note),note.hide(),beginEdit()},addColumn=function(ident,name,locked,notes,colour){let headerStyle='style="border-top: 10px solid #'.concat(colour,'"');var iseditable=isEditor,nameCache=null,column=(0,_jquery.default)('
')),columnHeader=(0,_jquery.default)('
'),columnSort=(0,_jquery.default)('
'),columnName=(0,_jquery.default)('
'+name+"
"),columnContent=(0,_jquery.default)('
'),columnNewContent=(0,_jquery.default)('
');if(3!=sortby&&columnHeader.append(columnSort),columnHeader.append(columnName),options.hideheaders&&columnName.addClass("d-none"),columnSort.on("click",(function(){sortNotes(columnContent,!0)})),iseditable){column.addClass("mod_board_editablecolumn");const lockIcon=locked?"fa-lock":"fa-unlock",lockElement=(0,_jquery.default)('
')),lockstring=locked?"aria_column_locked":"aria_column_unlocked";(0,_str.get_string)(lockstring,"mod_board",name).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)})),handleAction(lockElement,(()=>{const lockColumn="true"!==column.attr("data-locked");serviceCall("lock_column",{id:ident,status:lockColumn},(function(result){const columnName=column.find(".mod_board_column_name").text();result.status&&(lockColumn?(lockElement.removeClass("fa-unlock").addClass("fa-lock"),column.attr("data-locked","true"),column.find(".board_button.newnote").addClass("d-none"),(0,_str.get_string)("aria_column_locked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))):(lockElement.removeClass("fa-lock").addClass("fa-unlock"),column.attr("data-locked","false"),column.find(".board_button.newnote").removeClass("d-none"),(0,_str.get_string)("aria_column_unlocked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))),lastHistoryId=result.historyid,updateSortable())}))})),columnHeader.append(lockElement),columnHeader.addClass("icon-size-3");const moveElement=(0,_jquery.default)('
');columnHeader.append(moveElement),_movecolumnsdialog.default.init(moveColumn);var removeElement=(0,_jquery.default)('
');handleAction(removeElement,(()=>{_notification.default.confirm(strings.remove_column_title,(0,_str.get_string)("remove_column_text","mod_board",getColumnName(ident)),strings.delete,strings.Cancel,(function(){serviceCall("delete_column",{id:ident},(function(result){result.status&&(column.remove(),lastHistoryId=result.historyid)}))}))})),columnHeader.append(removeElement)}if(column.append(columnHeader),column.append(columnContent),column.append(columnNewContent),iseditable&&(!function(elem,callback,callBeforeOnKeyEditing){if(elem.is(":editable"))throw new Error("handleEditableAction - must be called before setting the element as editable");elem.on("dblclick keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode)||elem.is(":editing"))return;if(e.preventDefault(),callBeforeOnKeyEditing&&callback(),elem.editable("open"),callBeforeOnKeyEditing)return}callback()}))}(columnName,(function(){nameCache=columnName.html()}),!0),columnName.editable({toggleFontSize:!1,closeOnEnter:!0,callback:function(data){data.content?serviceCall("update_column",{id:ident,name:columnName.html()},(function(result){result.status?(lastHistoryId=result.historyid,updateColumnAria(ident)):(columnName.html(nameCache),nameCache=null)}),(function(){columnName.html(nameCache),nameCache=null})):(columnName.html(nameCache),nameCache=null)}})),!isReadOnlyBoard){const newNoteButton=(0,_jquery.default)('
');columnNewContent.append(newNoteButton),"true"===column.attr("data-locked")&&newNoteButton.addClass("d-none"),handleAction(columnNewContent.find(".newnote"),(function(){addNote(ident,0,null,null,null,{id:userId},0,0)}))}var lastOne=(0,_jquery.default)(".mod_board .board_column_hasdata").last();if(lastOne.length?column.insertAfter(lastOne):(0,_jquery.default)(".mod_board").append(column),notes)for(var index in notes){let sortorder=3==sortby?notes[index].sortorder:notes[index].timecreated;addNote(ident,notes[index].id,notes[index].heading,notes[index].content,{type:notes[index].type,info:notes[index].info,url:notes[index].url},{id:notes[index].userid,fullname:notes[index].fullname},sortorder,notes[index].rating)}sortNotes(columnContent),updateColumnAria(ident),(isEditor||1==usersCanEdit)&&updateSortable(),isEditor&&columnSorting()};const getColumnName=id=>(0,_jquery.default)(".board_column[data-ident='".concat(id,"']")).find(".mod_board_column_name").html();const selectHeadingColour=()=>{let colCount=(0,_jquery.default)(".board_column").length-1,colourCount=options.colours.length;return options.colours[colCount%colourCount]};var updateNote=function(note,heading,data){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteText.html(data.content),noteHeading.html(data.heading),setAttachment(note,data.attachment),updateNoteAria(data.id),noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())},processBoardHistory=function(){serviceCall("board_history",{id:board.id,ownerid:ownerId,since:lastHistoryId},(function(boardhistory){for(var index in boardhistory){var item=boardhistory[index];if(item.boardid==board.id){var data=JSON.parse(item.content);if("add_note"==item.action){let sortorder=3==sortby?data.sortorder:data.timecreated;addNote(data.columnid,data.id,data.heading,data.content,data.attachment,{id:item.userid},sortorder,data.rating),updateNoteAria(data.id),sortNotes((0,_jquery.default)(".board_column[data-ident="+data.columnid+"] .board_column_content"))}else if("update_note"==item.action){let note=getNote(data.id),formModal=editModal,historyData=data;if(note){getNoteHeadingForNote(note);editingNote==data.id?_notification.default.confirm(strings.note_changed_title,strings.note_changed_text,strings.Ok,strings.Cancel,(function(){formModal.hide(),updateNote(note,0,historyData),stopNoteEdit()})):updateNote(note,0,data)}}else if("delete_note"==item.action){editingNote==data.id&&(_notification.default.alert(strings.warning,strings.note_deleted_text),stopNoteEdit());let note=getNote(data.id);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}else if("add_column"==item.action)addColumn(data.id,data.name,!1,{},selectHeadingColour());else if("move_column"==item.action){const board=(0,_jquery.default)(".mod_board");data.sortorder.forEach((column=>{board.find(".board_column[data-ident='".concat(column,"']")).detach().appendTo(board)}))}else if("update_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"'] .mod_board_column_name").html(data.name),updateColumnAria(data.id);else if("lock_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").attr("data-locked",data.locked),data.locked?(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").addClass("d-none"):(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").removeClass("d-none"),updateSortable();else if("delete_column"==item.action){var column=(0,_jquery.default)(".board_column[data-ident='"+data.id+"']");editingNote&&column.find('.board_note[data-ident="'+editingNote+'"]').length&&stopNoteEdit(),column.remove()}else if("rate_note"==item.action){var note=getNote(data.id);note.find(".mod_board_rating").html(data.rating),2==sortby&&sortNotes(note.closest(".board_column_content"))}lastHistoryId=item.id}}updateBoard()}))},updateBoard=function(instant){instant?processBoardHistory():options.history_refresh>0&&(reloadTimer&&stopUpdating(),reloadTimer=setTimeout(processBoardHistory,1e3*options.history_refresh))},stopUpdating=function(){clearTimeout(reloadTimer),reloadTimer=null},sortNotes=function(content,toggle){var desc,asc,sortCol=(0,_jquery.default)(content).parent().find(".mod_board_column_sort"),direction=(0,_jquery.default)(content).data("sort");if(direction||(direction=2==sortby?"desc":"asc"),toggle&&(direction="asc"==direction?"desc":"asc"),"asc"==direction?(sortCol.removeClass("fa-angle-down"),sortCol.addClass("fa-angle-up")):(sortCol.removeClass("fa-angle-up"),sortCol.addClass("fa-angle-down")),(0,_jquery.default)(content).data("sort",direction),1==sortby)desc=function(a,b){return(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(2==sortby)desc=function(a,b){return(0,_jquery.default)(b).find(".mod_board_rating").text()-(0,_jquery.default)(a).find(".mod_board_rating").text()||(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).find(".mod_board_rating").text()-(0,_jquery.default)(b).find(".mod_board_rating").text()||(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(3==sortby){let sortElements=(a,b)=>(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder");return void(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort(sortElements).appendTo((0,_jquery.default)(content))}(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort("asc"===direction?asc:desc).appendTo((0,_jquery.default)(content))},updateSortable=function(){let fromColumnID;(0,_jquery.default)(".board_column[data-locked='false'] .board_column_content").sortable({connectWith:".board_column[data-locked='false'] .board_column_content",cancel:".mod_board_nosort",handle:".move_note",start:function(_,ui){fromColumnID=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){var note=(0,_jquery.default)(ui.item),tocolumn=note.closest(".board_column"),elem=(0,_jquery.default)(this),noteid=note.data("ident"),columnid=tocolumn.data("ident");let sortorder=tocolumn.find(".board_column_content").children().index((0,_jquery.default)(".board_note[data-ident=".concat(noteid,"]")));moveNote(fromColumnID,{id:noteid,columnid:columnid,ownerid:ownerId,sortorder:sortorder},elem)}})};const moveNote=(fromColumnID,payload,elem)=>{updateSortOrders(fromColumnID,payload.columnid,payload.id,payload.sortorder),serviceCall("move_note",payload,(result=>{result.status?(lastHistoryId=result.historyid,updateNoteAria(payload.id),updateBoard(),sortNotes((0,_jquery.default)(".board_column[data-ident=".concat(payload.columnid,"] .board_column_content")))):elem&&elem.sortable("cancel")}))},columnSorting=()=>{let movingColumnId;(0,_jquery.default)(".mod_board").sortable({connectWith:".mod_board",axis:"x",containment:".mod_board_wrapper",cancel:".mod_board_nosort",handle:".mod_column_move",start:function(_,ui){movingColumnId=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){let column=(0,_jquery.default)(ui.item),sortorder=(0,_jquery.default)(".mod_board").find(".board_column").index(column);moveColumn({id:movingColumnId,sortorder:sortorder})}})},moveColumn=payload=>{serviceCall("move_column",payload,!1)},updateSortOrders=(fromColumnID,toColumnID,noteID,newSortOrder)=>{let toColumn=(0,_jquery.default)(".board_column[data-ident=".concat(toColumnID,"] .board_column_content")),movedNote=(0,_jquery.default)(".board_note[data-ident=".concat(noteID,"]")),oldSortOrder=movedNote.data("sortorder"),toChildren=toColumn.children();if(fromColumnID==toColumnID)toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");oldSortOrder=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1):oldSortOrder>newSortOrder&&sortOrder>=newSortOrder&&sortOrder<=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)}));else{let fromChildren=(0,_jquery.default)(".board_column[data-ident=".concat(fromColumnID,"] .board_column_content")).children();toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>=newSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)})),fromChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1)}))}movedNote.data("sortorder",newSortOrder)};var getBody=function(noteid,columnid,ownerId){var params={noteid:noteid,columnid:columnid,ownerid:ownerId};return _fragment.default.loadFragment("mod_board","note_form",contextid,params)},showModalForm=function(note){let title,noteId=0,columnId=note.data("column"),columnIdentifier=(0,_jquery.default)(".board_column[data-ident="+columnId+"]").find(".mod_board_column_name").text();note.data("ident")?(noteId=note.data("ident"),title=strings.modal_title_edit.replace("{column}",columnIdentifier)):title=strings.modal_title_new.replace("{column}",columnIdentifier),_modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:title,body:getBody(noteId,columnId,ownerId),large:!0,removeOnClose:!0}).then((function(modal){return modal.getBodyPromise().then((function(){let saveInProgress=!1;editModal=modal,modal.setLarge(),modal.setSaveButtonText(strings.post_button_text),modal.setButtonText("cancel",strings.cancel_button_text),modal.getRoot().on(_modal_events.default.hidden,(function(){stopNoteEdit(),note.data("ident")||note.remove()})),modal.getRoot().on(_modal_events.default.save,(function(e){e.preventDefault(),modal.getRoot().find("form").submit()}));var changeEvent=document.createEvent("HTMLEvents");if(changeEvent.initEvent("change",!0,!0),modal.getRoot().on("submit","form",(function(e){if(e.preventDefault(),saveInProgress)return;if(saveInProgress=!0,modal.getRoot().find("form").get(0).reportValidity()){modal.getRoot().find(":input").each((function(index,element){element.dispatchEvent(changeEvent)}));var invalid=_jquery.default.merge(modal.getRoot().find('[aria-invalid="true"]'),modal.getRoot().find(".error"),modal.getRoot().find(":invalid"));if(invalid.length)return invalid.first().focus(),void(saveInProgress=!1);var formData=JSON.stringify(modal.getRoot().find("form").serialize());serviceCall("submit_form",{contextid:contextid,jsonformdata:formData},(function(result){result.status?("insert"==result.action?(lastHistoryId=result.historyid,note.remove(),addNote(columnId,result.note.id,result.note.heading,result.note.content,{type:result.note.type,info:result.note.info,url:result.note.url},{id:result.note.userid},result.note.timecreated,result.note.rating),sortNotes((0,_jquery.default)(".board_column[data-ident="+columnId+"] .board_column_content")),updateNoteAria(result.note.id)):(lastHistoryId=result.historyid,getNoteTextForNote(note).html(result.note.content),getNoteHeadingForNote(note).html(result.note.heading),updateNoteAria(result.note.id),setAttachment(note,{type:result.note.type,info:result.note.info,url:result.note.url})),stopNoteEdit(),Y.use("moodle-core-formchangechecker",(function(){M.core_formchangechecker.reset_form_dirty_state()})),modal.destroy()):modal.destroy()}))}else saveInProgress=!1})),1==mediaSelection){modal.getRoot().find("#fitem_id_mediatype").hide();let mediaSelect=modal.getRoot().find("#fitem_id_mediatype select"),ytButton=modal.getRoot().find(".mod_board_attachment_button.youtube_button"),pictureButton=modal.getRoot().find(".mod_board_attachment_button.image_button"),linkButton=modal.getRoot().find(".mod_board_attachment_button.link_button"),updateMediaButtons=function(){switch(ytButton.removeClass("selected"),pictureButton.removeClass("selected"),linkButton.removeClass("selected"),mediaSelect.val()){case"1":ytButton.addClass("selected");break;case"2":pictureButton.addClass("selected");break;case"3":linkButton.addClass("selected")}};updateMediaButtons(),handleAction(ytButton,(function(){"1"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(1),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(pictureButton,(function(){"2"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(2),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(linkButton,(function(){"3"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(3),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)}))}else modal.getRoot().find("#fitem_id_mediabuttons").hide();return function(note,modal){let addYoutube,addImage,addLink,postButton,cancelButton,columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text(),modalRoot=modal.getRoot();if(note.data("ident")){var noteIdentifier=textIdentifierForNote(note);postButton=strings.aria_postedit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),cancelButton=strings.aria_canceledit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addYoutube=strings.aria_addmedia.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addImage=strings.aria_addmedia.replace("{type}",strings.option_image).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addLink=strings.aria_addmedia.replace("{type}",strings.option_link).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)}else postButton=strings.aria_postnew.replace("{column}",columnIdentifier),cancelButton=strings.aria_cancelnew.replace("{column}",columnIdentifier),addYoutube=strings.aria_addmedianew.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier),addImage=strings.aria_addmedianew.replace("{type}",strings.option_image).replace("{column}",columnIdentifier),addLink=strings.aria_addmedianew.replace("{type}",strings.option_link).replace("{column}",columnIdentifier);1==mediaSelection&&(modalRoot.find(".mod_board_attachment_button.youtube_button").attr("aria-label",addYoutube),modalRoot.find(".mod_board_attachment_button.youtube_button").attr("title",addYoutube),modalRoot.find(".mod_board_attachment_button.image_button").attr("aria-label",addImage),modalRoot.find(".mod_board_attachment_button.image_button").attr("title",addImage),modalRoot.find(".mod_board_attachment_button.link_button").attr("aria-label",addLink),modalRoot.find(".mod_board_attachment_button.link_button").attr("title",addLink));let button=modalRoot.find(modal.getActionSelector("save"));button&&button.attr("aria-label",postButton),button=modalRoot.find(modal.getActionSelector("cancel")),button&&button.attr("aria-label",cancelButton)}(note,modal),modal.show(),modal})).catch(_notification.default.exception),modal})).catch(_notification.default.exception)},fullScreenNote=(ident,notecontent)=>{const heading=getNoteHeadingForNote(notecontent).html(),modalBody=(0,_jquery.default)(document.createElement("div"));modalBody.addClass("mod_board_note_content");const text=getNoteTextForNote(notecontent);text&&modalBody.append(text.clone());const preview=(note=notecontent,(0,_jquery.default)(note).find(".mod_board_preview"));var note;preview&&modalBody.append(preview.clone());const commentArea=(0,_jquery.default)(document.createElement("div"));commentArea.attr("data-region","comment-area"),modalBody.append(commentArea),_comments.default.fetchFor(ident,commentArea),_modal_factory.default.create({type:_modal_factory.default.types.CANCEL,title:heading,body:modalBody}).then((function(modal){return modal.setLarge(),modal.show(),modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal}),this).catch(_notification.default.exception)},init=function(){serviceCall("get_board",{id:board.id,ownerid:ownerId},(function(columns){if(columns)for(var index in columns)addColumn(columns[index].id,columns[index].name,columns[index].locked,columns[index].notes||{},options.colours[columns[index].id%options.colours.length]);var column,newBusy;isEditor&&(column=(0,_jquery.default)('
'),newBusy=!1,column.append('
'),handleAction(column.find(".newcolumn"),(function(){newBusy||(newBusy=!0,serviceCall("add_column",{boardid:board.id,name:strings.default_column_heading},(function(result){addColumn(result.id,strings.default_column_heading,!1,{},selectHeadingColour()),lastHistoryId=result.historyid,newBusy=!1}),(function(){newBusy=!1})))})),(0,_jquery.default)(".mod_board").append(column)),lastHistoryId=board.historyid,isEditor&&(updateSortable(),columnSorting()),updateBoard()}))},stringsInfo=[];for(var string in strings)stringsInfo.push({key:string,component:"mod_board"});_jquery.default.when((0,_str.get_strings)(stringsInfo)).done((function(results){var index=0;for(string in strings)strings[string]=results[index++];init()}))},_jquery=_interopRequireDefault(_jquery),_ajax=_interopRequireDefault(_ajax),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_fragment=_interopRequireDefault(_fragment),_comments=_interopRequireDefault(_comments),_movenotesdialog=_interopRequireDefault(_movenotesdialog),_movecolumnsdialog=_interopRequireDefault(_movecolumnsdialog);const isAriaTriggerKey=function(key){return 13==key||32==key},encodeText=function(rawText){return(0,_jquery.default)("
").text(rawText).html()},decodeText=function(encodedText){return(0,_jquery.default)("
").html(encodedText).text()},handleAction=function(elem,callback){return elem.on("click keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode))return;e.preventDefault()}callback(),e.preventDefault()}))};return _exports.default})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=function(settings){var strings={default_column_heading:"",post_button_text:"",cancel_button_text:"",remove_note_title:"",remove_note_text:"",remove_column_title:"",note_changed_title:"",note_changed_text:"",note_deleted_text:"",rate_note_title:"",rate_note_text:"",rate_remove_note_text:"",Ok:"",delete:"",Cancel:"",warning:"",modal_title_new:"",modal_title_edit:"",option_youtube:"",option_image:"",option_link:"",aria_newcolumn:"",aria_newpost:"",aria_deletecolumn:"",aria_movecolumn:"",aria_deletepost:"",aria_movepost:"",aria_editpost:"",aria_addmedia:"",aria_addmedianew:"",aria_deleteattachment:"",aria_postedit:"",aria_canceledit:"",aria_postnew:"",aria_cancelnew:"",aria_ratepost:"",invalid_file_extension:"",invalid_file_size_min:"",invalid_file_size_max:"",invalid_youtube_url:""},options=JSON.parse(settings.settings)||{},board=options.board||{},contextid=options.contextid;var reloadTimer=null,lastHistoryId=null,isEditor=options.isEditor||!1,usersCanEdit=options.usersCanEdit,userId=parseInt(options.userId)||-1,userFullname=options.userFullname,ownerId=parseInt(options.ownerId),mediaSelection=options.mediaselection||1,editingNote=0,isReadOnlyBoard=options.readonly||!1,showauthorofnote=options.showauthorofnote||!1,allowshowauthorofnoteonboard=options.allowshowauthorofnoteonboard||!1,ratingenabled=options.ratingenabled,sortby=options.sortby||1,editModal=null,enableblanktarget=1===parseInt(options.enableblanktarget),serviceCall=function(method,args,callback,failcallback){"board_history"!==method&&stopUpdating(),function(method,args,callback,failcallback){_ajax.default.call([{methodname:"mod_board_"+method,args:args,done:function(data){callback(data)},fail:function(error){_notification.default.exception(error),failcallback&&failcallback(error)}}])}(method,args,(function(){callback&&callback.apply(null,arguments),"board_history"!==method&&"get_board"!=method&&updateBoard(!0)}),failcallback)},getNote=function(ident){return(0,_jquery.default)(".board_note[data-ident='"+ident+"']")},getNoteTextForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_text")},getNoteHeadingForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_heading")},getNoteBorderForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_border")},getNoteAttachmentsForNote=function(note){return(0,_jquery.default)(note).find(".mod_board_note_attachment")},textIdentifierForNote=function(note){var noteText=getNoteTextForNote(note).html(),noteHeading=getNoteHeadingForNote(note).html(),noteAttachment=attachmentDataForNote(note);return noteHeading.length>0?noteHeading:noteText.length>0?noteText.replace(//gi," ").replace(/\n/g," ").split(/\s+/).slice(0,5).join(" "):noteAttachment.info&¬eAttachment.info.length>0?noteAttachment.info:null},updateNoteAria=function(noteId){var note=getNote(noteId),columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text();if(noteId){var noteIdentifier=textIdentifierForNote(note),deleteNoteString=strings.aria_deletepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier);note.find(".delete_note").attr("aria-label",deleteNoteString).attr("title",deleteNoteString);var moveNoteString=strings.aria_movepost.replace("{post}",noteIdentifier);note.find(".move_note").attr("aria-label",moveNoteString).attr("title",moveNoteString);var editNoteString=strings.aria_editpost.replace("{post}",noteIdentifier);note.find(".edit_note").attr("aria-label",editNoteString).attr("title",editNoteString),note.find(".mod_board_rating").attr("aria-label",strings.aria_ratepost.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)),note.find(".note_ariatext").html(noteIdentifier)}},updateColumnAria=function(columnId){var column=(0,_jquery.default)(".board_column[data-ident="+columnId+"]"),columnIdentifier=column.find(".mod_board_column_name").text(),newNoteString=strings.aria_newpost.replace("{column}",columnIdentifier),moveColumnString=strings.aria_movecolumn.replace("{column}",columnIdentifier),deleteColumnString=strings.aria_deletecolumn.replace("{column}",columnIdentifier);column.find(".newnote").attr("aria-label",newNoteString).attr("title",newNoteString),column.find(".mod_column_move").attr("aria-label",moveColumnString).attr("title",moveColumnString),column.find(".delete_column").attr("aria-label",deleteColumnString).attr("title",deleteColumnString),column.find(".board_note").each((function(index,note){updateNoteAria((0,_jquery.default)(note).data("ident"))}))},stopNoteEdit=function(){if(editingNote){var note=getNote(editingNote);if(note){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())}editingNote=0}else getNote(0).remove()};const sortAfterDelete=(columnID,sortorder)=>{let column=(columnID=>(0,_jquery.default)(".board_column[data-ident='".concat(columnID,"'] .board_column_content")))(columnID);column.children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so-1)}))};var setAttachment=function(note,attachment){var noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment){attachment?attachment.type+="":attachment={type:"0"};var attType=noteAttachment.find(".mod_board_type");attType.val(attachment.type?attachment.type:"0"),attType.val()>"0"&&(noteAttachment.find(".info").val(decodeText(attachment.info)),noteAttachment.find(".url").val(decodeText(attachment.url))),function(note){var noteAttachment=getNoteAttachmentsForNote(note),type=noteAttachment.find(".mod_board_type").val(),attachmentInfo=noteAttachment.find(".info"),attachmentUrl=noteAttachment.find(".url"),attachmentFile=noteAttachment.find(".mod_board_file");type>"0"?(attachmentInfo.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_info"]),attachmentUrl.prop("placeholder",strings["option_"+attachmentTypeToString(type)+"_url"]),attachmentInfo.show(),2==type&&FileReader?(attachmentFile.show(),attachmentUrl.hide()):(attachmentFile.hide(),attachmentUrl.show())):(attachmentInfo.hide(),attachmentUrl.hide(),attachmentFile.hide(),attachmentInfo.val(""),attachmentUrl.val(""))}(note)}previewAttachment(note,attachment)},attachmentDataForNote=function(note){var attachment={type:0,info:null,url:null,filename:null,filecontents:null},noteAttachment=getNoteAttachmentsForNote(note);if(noteAttachment.length){attachment.type=noteAttachment.find(".mod_board_type").val(),attachment.info=encodeText(noteAttachment.find(".info").val()),attachment.url=encodeText(noteAttachment.find(".url").val());var fileElem=noteAttachment.find(".mod_board_file>input");fileElem.data("filename")&&(attachment.filename=fileElem.data("filename"),attachment.filecontents=fileElem.data("filecontents"))}return attachment.info&&attachment.info.length||attachment.url&&attachment.url.length||attachment.filename||(attachment.type=0),attachment},attachmentTypeToString=function(type){switch(type){case"1":return"youtube";case"2":return"image";case"3":return"link";default:return null}};var previewAttachment=function(note,attachment){var elem=note.find(".mod_board_preview");if(attachment||(attachment=attachmentDataForNote(note)),getNoteTextForNote(note).html().length?elem.removeClass("mod_board_notext"):elem.addClass("mod_board_notext"),elem.removeClass("wrapper_youtube"),elem.removeClass("wrapper_image"),elem.removeClass("wrapper_url"),attachment.filename&&2==parseInt(attachment.type))elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();else if(attachment.url){const blanktarget=enableblanktarget?' target="_blank"':"";switch(parseInt(attachment.type)){case 1:{let url=(url=>{let videoID=url.match(/(\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/);return videoID&&void 0!==videoID[2]&&11===videoID[2].length?"https://www.youtube-nocookie.com/embed/".concat(videoID[2]):null})(attachment.url);null===url?elem.html(strings.invalid_youtube_url):(elem.html(''),elem.addClass("wrapper_youtube").addClass("position-relative")),elem.show()}break;case 2:elem.html('').concat(attachment.info,'')),elem.addClass("wrapper_image"),elem.show();break;case 3:elem.html('"+(attachment.info||attachment.url)+""),elem.addClass("wrapper_url"),elem.show();break;default:elem.html(""),elem.hide()}}else elem.html(""),elem.hide()},addNote=function(columnid,ident,heading,content,attachment,owner,sortorder,rating){var ismynote=owner.id==userId||!ident,iseditable=isEditor||ismynote&&!isReadOnlyBoard;if(!ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}if(3==sortby){(0,_jquery.default)(".board_column[data-ident='".concat(columnid,"'] .board_column_content")).children().filter(((_,element)=>parseInt((0,_jquery.default)(element).data("sortorder"))>=parseInt(sortorder))).each(((_,element)=>{let so=(0,_jquery.default)(element).data("sortorder");(0,_jquery.default)(element).data("sortorder",so+1)}))}var note=(0,_jquery.default)('
');ismynote&¬e.addClass("mod_board_mynote"),iseditable&¬e.addClass("mod_board_editablenote"),ismynote||iseditable||note.addClass("mod_board_nosort");var notecontent=(0,_jquery.default)('
'),notecontrols=(0,_jquery.default)('
'),noteHeading=(0,_jquery.default)('
'+(heading||"")+"
"),noteAuthorusername=(0,_jquery.default)(""),noteBorder=(0,_jquery.default)('
'),noteText=(0,_jquery.default)('
'+(content||"")+"
"),noteAriaText=(0,_jquery.default)(''),attachmentPreview=(0,_jquery.default)('
');if(1==allowshowauthorofnoteonboard&&1==showauthorofnote){let fullname="";fullname=ismynote?userFullname:owner.fullname,noteAuthorusername='
'+fullname+"
"}notecontent.append(noteHeading),notecontent.append(noteAuthorusername),notecontent.append(noteBorder),notecontent.append(noteText),notecontent.append(noteAriaText),notecontent.append(attachmentPreview),note.append(notecontent);var columnContent=(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_content"),beginEdit=()=>{!function(ident){if(editingNote){if(editingNote==ident)return;stopNoteEdit()}if(ident){var pendingNote=getNote(0);pendingNote&&pendingNote.remove()}var note=getNote(ident);note&&(showModalForm(note),ident&&(editingNote=ident))}(ident)};if(ident){if(ratingenabled){note.addClass("mod_board_rateablenote");var rateElement=(0,_jquery.default)('
'.concat(rating,"
"));handleAction(rateElement,(()=>{!function(ident){if(ratingenabled&&!isReadOnlyBoard){var note=getNote(ident),rating=note.find(".mod_board_rating");rating.data("disabled")||(rating.data("disabled",!0),serviceCall("can_rate_note",{id:ident},(function(result){if(result.canrate){const rateRemoveText=result.hasrated?strings.rate_remove_note_text:strings.rate_note_text;_notification.default.confirm(strings.rate_note_title,rateRemoveText,strings.Ok,strings.Cancel,(function(){serviceCall("rate_note",{id:ident},(function(result){result.status&&(lastHistoryId=result.historyid,rating.html(" ".concat(result.rating," ")),2==sortby&&sortNotes(note.closest(".board_column_content"))),rating.data("disabled",!1)}))})).then((function(rateModal){rateModal.getRoot().on(_modal_events.default.hidden,(function(){rating.data("disabled",!1)}))}))}})))}}(ident)})),notecontrols.append(rateElement)}if(iseditable){var removeElement=(0,_jquery.default)('
');if(handleAction(removeElement,(()=>{!function(ident){_notification.default.confirm(strings.remove_note_title,strings.remove_note_text,strings.delete,strings.Cancel,(function(){serviceCall("delete_note",{id:ident},(function(result){if(result.status){lastHistoryId=result.historyid;let note=getNote(ident);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}}))}))}(ident)})),notecontrols.append(removeElement),1==usersCanEdit||isEditor){var moveElement=(0,_jquery.default)('
');notecontrols.append(moveElement),_movenotesdialog.default.init(ownerId,moveNote)}var editElement=(0,_jquery.default)('
');notecontrols.append(editElement),handleAction(editElement,(()=>{beginEdit()})),updateSortable(),setAttachment(note,attachment)}else previewAttachment(note,attachment);note.append(notecontrols),handleAction(notecontent,(()=>fullScreenNote(ident,notecontent))),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide());var lastOne=columnContent.find(".board_note").last();lastOne.length?note.insertAfter(lastOne):columnContent.prepend(note)}else(0,_jquery.default)(".board_column[data-ident="+columnid+"] .board_column_newcontent").append(note),note.hide(),beginEdit()},addColumn=function(ident,name,locked,notes,colour){let headerStyle='style="border-top: 10px solid #'.concat(colour,'"');var iseditable=isEditor,nameCache=null,column=(0,_jquery.default)('
')),columnHeader=(0,_jquery.default)('
'),columnSort=(0,_jquery.default)('
'),columnName=(0,_jquery.default)('
'+name+"
"),columnContent=(0,_jquery.default)('
'),columnNewContent=(0,_jquery.default)('
');if(3!=sortby&&columnHeader.append(columnSort),columnHeader.append(columnName),options.hideheaders&&columnName.addClass("d-none"),columnSort.on("click",(function(){sortNotes(columnContent,!0)})),iseditable){column.addClass("mod_board_editablecolumn");const lockIcon=locked?"fa-lock":"fa-unlock",lockElement=(0,_jquery.default)('
')),lockstring=locked?"aria_column_locked":"aria_column_unlocked";(0,_str.get_string)(lockstring,"mod_board",name).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)})),handleAction(lockElement,(()=>{const lockColumn="true"!==column.attr("data-locked");serviceCall("lock_column",{id:ident,status:lockColumn},(function(result){const columnName=column.find(".mod_board_column_name").text();result.status&&(lockColumn?(lockElement.removeClass("fa-unlock").addClass("fa-lock"),column.attr("data-locked","true"),column.find(".board_button.newnote").addClass("d-none"),(0,_str.get_string)("aria_column_locked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))):(lockElement.removeClass("fa-lock").addClass("fa-unlock"),column.attr("data-locked","false"),column.find(".board_button.newnote").removeClass("d-none"),(0,_str.get_string)("aria_column_unlocked","mod_board",columnName).done((function(str){lockElement.attr("aria-label",str),lockElement.attr("title",str)}))),lastHistoryId=result.historyid,updateSortable())}))})),columnHeader.append(lockElement),columnHeader.addClass("icon-size-3");const moveElement=(0,_jquery.default)('
');columnHeader.append(moveElement),_movecolumnsdialog.default.init(moveColumn);var removeElement=(0,_jquery.default)('
');handleAction(removeElement,(()=>{_notification.default.confirm(strings.remove_column_title,(0,_str.get_string)("remove_column_text","mod_board",getColumnName(ident)),strings.delete,strings.Cancel,(function(){serviceCall("delete_column",{id:ident},(function(result){result.status&&(column.remove(),lastHistoryId=result.historyid)}))}))})),columnHeader.append(removeElement)}if(column.append(columnHeader),column.append(columnContent),column.append(columnNewContent),iseditable&&(!function(elem,callback,callBeforeOnKeyEditing){if(elem.is(":editable"))throw new Error("handleEditableAction - must be called before setting the element as editable");elem.on("dblclick keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode)||elem.is(":editing"))return;if(e.preventDefault(),callBeforeOnKeyEditing&&callback(),elem.editable("open"),callBeforeOnKeyEditing)return}callback()}))}(columnName,(function(){nameCache=columnName.html()}),!0),columnName.editable({toggleFontSize:!1,closeOnEnter:!0,callback:function(data){data.content?serviceCall("update_column",{id:ident,name:columnName.html()},(function(result){result.status?(lastHistoryId=result.historyid,updateColumnAria(ident)):(columnName.html(nameCache),nameCache=null)}),(function(){columnName.html(nameCache),nameCache=null})):(columnName.html(nameCache),nameCache=null)}})),!isReadOnlyBoard){const newNoteButton=(0,_jquery.default)('
');columnNewContent.append(newNoteButton),"true"===column.attr("data-locked")&&newNoteButton.addClass("d-none"),handleAction(columnNewContent.find(".newnote"),(function(){addNote(ident,0,null,null,null,{id:userId},0,0)}))}var lastOne=(0,_jquery.default)(".mod_board .board_column_hasdata").last();if(lastOne.length?column.insertAfter(lastOne):(0,_jquery.default)(".mod_board").append(column),notes)for(var index in notes){let sortorder=3==sortby?notes[index].sortorder:notes[index].timecreated;addNote(ident,notes[index].id,notes[index].heading,notes[index].content,{type:notes[index].type,info:notes[index].info,url:notes[index].url},{id:notes[index].userid,fullname:notes[index].fullname},sortorder,notes[index].rating)}sortNotes(columnContent),updateColumnAria(ident),(isEditor||1==usersCanEdit)&&updateSortable(),isEditor&&columnSorting()};const getColumnName=id=>(0,_jquery.default)(".board_column[data-ident='".concat(id,"']")).find(".mod_board_column_name").html();const selectHeadingColour=()=>{let colCount=(0,_jquery.default)(".board_column").length-1,colourCount=options.colours.length;return options.colours[colCount%colourCount]};var updateNote=function(note,heading,data){var noteHeading=getNoteHeadingForNote(note),noteText=getNoteTextForNote(note),noteBorder=getNoteBorderForNote(note);noteText.html(data.content),noteHeading.html(data.heading),setAttachment(note,data.attachment),updateNoteAria(data.id),noteHeading.show(),noteBorder.show(),noteText.show(),noteHeading.html()||(noteHeading.hide(),noteBorder.hide()),!noteText.html()&¬eHeading.html()&&(noteText.hide(),noteBorder.hide())},processBoardHistory=function(){serviceCall("board_history",{id:board.id,ownerid:ownerId,since:lastHistoryId},(function(boardhistory){for(var index in boardhistory){var item=boardhistory[index];if(item.boardid==board.id){var data=JSON.parse(item.content);if("add_note"==item.action){let sortorder=3==sortby?data.sortorder:data.timecreated;addNote(data.columnid,data.id,data.heading,data.content,data.attachment,{id:item.userid,fullname:item.userid+" "+item.fullname},sortorder,data.rating),updateNoteAria(data.id),sortNotes((0,_jquery.default)(".board_column[data-ident="+data.columnid+"] .board_column_content"))}else if("update_note"==item.action){let note=getNote(data.id),formModal=editModal,historyData=data;if(note){getNoteHeadingForNote(note);editingNote==data.id?_notification.default.confirm(strings.note_changed_title,strings.note_changed_text,strings.Ok,strings.Cancel,(function(){formModal.hide(),updateNote(note,0,historyData),stopNoteEdit()})):updateNote(note,0,data)}}else if("delete_note"==item.action){editingNote==data.id&&(_notification.default.alert(strings.warning,strings.note_deleted_text),stopNoteEdit());let note=getNote(data.id);if(3==sortby){let columnID=note.data("column"),sortorder=note.data("sortorder");sortAfterDelete(columnID,sortorder)}note.remove()}else if("add_column"==item.action)addColumn(data.id,data.name,!1,{},selectHeadingColour());else if("move_column"==item.action){const board=(0,_jquery.default)(".mod_board");data.sortorder.forEach((column=>{board.find(".board_column[data-ident='".concat(column,"']")).detach().appendTo(board)}))}else if("update_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"'] .mod_board_column_name").html(data.name),updateColumnAria(data.id);else if("lock_column"==item.action)(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").attr("data-locked",data.locked),data.locked?(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").addClass("d-none"):(0,_jquery.default)(".board_column[data-ident='"+data.id+"']").find(".board_button.newnote").removeClass("d-none"),updateSortable();else if("delete_column"==item.action){var column=(0,_jquery.default)(".board_column[data-ident='"+data.id+"']");editingNote&&column.find('.board_note[data-ident="'+editingNote+'"]').length&&stopNoteEdit(),column.remove()}else if("rate_note"==item.action){var note=getNote(data.id);note.find(".mod_board_rating").html(data.rating),2==sortby&&sortNotes(note.closest(".board_column_content"))}lastHistoryId=item.id}}updateBoard()}))},updateBoard=function(instant){instant?processBoardHistory():options.history_refresh>0&&(reloadTimer&&stopUpdating(),reloadTimer=setTimeout(processBoardHistory,1e3*options.history_refresh))},stopUpdating=function(){clearTimeout(reloadTimer),reloadTimer=null},sortNotes=function(content,toggle){var desc,asc,sortCol=(0,_jquery.default)(content).parent().find(".mod_board_column_sort"),direction=(0,_jquery.default)(content).data("sort");if(direction||(direction=2==sortby?"desc":"asc"),toggle&&(direction="asc"==direction?"desc":"asc"),"asc"==direction?(sortCol.removeClass("fa-angle-down"),sortCol.addClass("fa-angle-up")):(sortCol.removeClass("fa-angle-up"),sortCol.addClass("fa-angle-down")),(0,_jquery.default)(content).data("sort",direction),1==sortby)desc=function(a,b){return(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(2==sortby)desc=function(a,b){return(0,_jquery.default)(b).find(".mod_board_rating").text()-(0,_jquery.default)(a).find(".mod_board_rating").text()||(0,_jquery.default)(b).data("sortorder")-(0,_jquery.default)(a).data("sortorder")},asc=function(a,b){return(0,_jquery.default)(a).find(".mod_board_rating").text()-(0,_jquery.default)(b).find(".mod_board_rating").text()||(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder")};else if(3==sortby){let sortElements=(a,b)=>(0,_jquery.default)(a).data("sortorder")-(0,_jquery.default)(b).data("sortorder");return void(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort(sortElements).appendTo((0,_jquery.default)(content))}(0,_jquery.default)("> .board_note",(0,_jquery.default)(content)).sort("asc"===direction?asc:desc).appendTo((0,_jquery.default)(content))},updateSortable=function(){let fromColumnID;(0,_jquery.default)(".board_column[data-locked='false'] .board_column_content").sortable({connectWith:".board_column[data-locked='false'] .board_column_content",cancel:".mod_board_nosort",handle:".move_note",start:function(_,ui){fromColumnID=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){var note=(0,_jquery.default)(ui.item),tocolumn=note.closest(".board_column"),elem=(0,_jquery.default)(this),noteid=note.data("ident"),columnid=tocolumn.data("ident");let sortorder=tocolumn.find(".board_column_content").children().index((0,_jquery.default)(".board_note[data-ident=".concat(noteid,"]")));moveNote(fromColumnID,{id:noteid,columnid:columnid,ownerid:ownerId,sortorder:sortorder},elem)}})};const moveNote=(fromColumnID,payload,elem)=>{updateSortOrders(fromColumnID,payload.columnid,payload.id,payload.sortorder),serviceCall("move_note",payload,(result=>{result.status?(lastHistoryId=result.historyid,updateNoteAria(payload.id),updateBoard(),sortNotes((0,_jquery.default)(".board_column[data-ident=".concat(payload.columnid,"] .board_column_content")))):elem&&elem.sortable("cancel")}))},columnSorting=()=>{let movingColumnId;(0,_jquery.default)(".mod_board").sortable({connectWith:".mod_board",axis:"x",containment:".mod_board_wrapper",cancel:".mod_board_nosort",handle:".mod_column_move",start:function(_,ui){movingColumnId=(0,_jquery.default)(ui.item).closest(".board_column").data("ident")},stop:function(_,ui){let column=(0,_jquery.default)(ui.item),sortorder=(0,_jquery.default)(".mod_board").find(".board_column").index(column);moveColumn({id:movingColumnId,sortorder:sortorder})}})},moveColumn=payload=>{serviceCall("move_column",payload,!1)},updateSortOrders=(fromColumnID,toColumnID,noteID,newSortOrder)=>{let toColumn=(0,_jquery.default)(".board_column[data-ident=".concat(toColumnID,"] .board_column_content")),movedNote=(0,_jquery.default)(".board_note[data-ident=".concat(noteID,"]")),oldSortOrder=movedNote.data("sortorder"),toChildren=toColumn.children();if(fromColumnID==toColumnID)toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");oldSortOrder=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1):oldSortOrder>newSortOrder&&sortOrder>=newSortOrder&&sortOrder<=oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)}));else{let fromChildren=(0,_jquery.default)(".board_column[data-ident=".concat(fromColumnID,"] .board_column_content")).children();toChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>=newSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder+1)})),fromChildren.each(((_,note)=>{let sortOrder=(0,_jquery.default)(note).data("sortorder");sortOrder>oldSortOrder&&(0,_jquery.default)(note).data("sortorder",sortOrder-1)}))}movedNote.data("sortorder",newSortOrder)};var getBody=function(noteid,columnid,ownerId){var params={noteid:noteid,columnid:columnid,ownerid:ownerId};return _fragment.default.loadFragment("mod_board","note_form",contextid,params)},showModalForm=function(note){let title,noteId=0,columnId=note.data("column"),columnIdentifier=(0,_jquery.default)(".board_column[data-ident="+columnId+"]").find(".mod_board_column_name").text();note.data("ident")?(noteId=note.data("ident"),title=strings.modal_title_edit.replace("{column}",columnIdentifier)):title=strings.modal_title_new.replace("{column}",columnIdentifier),_modal_factory.default.create({type:_modal_factory.default.types.SAVE_CANCEL,title:title,body:getBody(noteId,columnId,ownerId),large:!0,removeOnClose:!0}).then((function(modal){return modal.getBodyPromise().then((function(){let saveInProgress=!1;editModal=modal,modal.setLarge(),modal.setSaveButtonText(strings.post_button_text),modal.setButtonText("cancel",strings.cancel_button_text),modal.getRoot().on(_modal_events.default.hidden,(function(){stopNoteEdit(),note.data("ident")||note.remove()})),modal.getRoot().on(_modal_events.default.save,(function(e){e.preventDefault(),modal.getRoot().find("form").submit()}));var changeEvent=document.createEvent("HTMLEvents");if(changeEvent.initEvent("change",!0,!0),modal.getRoot().on("submit","form",(function(e){if(e.preventDefault(),saveInProgress)return;if(saveInProgress=!0,modal.getRoot().find("form").get(0).reportValidity()){modal.getRoot().find(":input").each((function(index,element){element.dispatchEvent(changeEvent)}));var invalid=_jquery.default.merge(modal.getRoot().find('[aria-invalid="true"]'),modal.getRoot().find(".error"),modal.getRoot().find(":invalid"));if(invalid.length)return invalid.first().focus(),void(saveInProgress=!1);var formData=JSON.stringify(modal.getRoot().find("form").serialize());serviceCall("submit_form",{contextid:contextid,jsonformdata:formData},(function(result){result.status?("insert"==result.action?(lastHistoryId=result.historyid,note.remove(),addNote(columnId,result.note.id,result.note.heading,result.note.content,{type:result.note.type,info:result.note.info,url:result.note.url},{id:result.note.userid},result.note.timecreated,result.note.rating),sortNotes((0,_jquery.default)(".board_column[data-ident="+columnId+"] .board_column_content")),updateNoteAria(result.note.id)):(lastHistoryId=result.historyid,getNoteTextForNote(note).html(result.note.content),getNoteHeadingForNote(note).html(result.note.heading),updateNoteAria(result.note.id),setAttachment(note,{type:result.note.type,info:result.note.info,url:result.note.url})),stopNoteEdit(),Y.use("moodle-core-formchangechecker",(function(){M.core_formchangechecker.reset_form_dirty_state()})),modal.destroy()):modal.destroy()}))}else saveInProgress=!1})),1==mediaSelection){modal.getRoot().find("#fitem_id_mediatype").hide();let mediaSelect=modal.getRoot().find("#fitem_id_mediatype select"),ytButton=modal.getRoot().find(".mod_board_attachment_button.youtube_button"),pictureButton=modal.getRoot().find(".mod_board_attachment_button.image_button"),linkButton=modal.getRoot().find(".mod_board_attachment_button.link_button"),updateMediaButtons=function(){switch(ytButton.removeClass("selected"),pictureButton.removeClass("selected"),linkButton.removeClass("selected"),mediaSelect.val()){case"1":ytButton.addClass("selected");break;case"2":pictureButton.addClass("selected");break;case"3":linkButton.addClass("selected")}};updateMediaButtons(),handleAction(ytButton,(function(){"1"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(1),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(pictureButton,(function(){"2"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(2),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)})),handleAction(linkButton,(function(){"3"===mediaSelect.val()?mediaSelect.val(0):mediaSelect.val(3),updateMediaButtons(),mediaSelect[0].dispatchEvent(changeEvent)}))}else modal.getRoot().find("#fitem_id_mediabuttons").hide();return function(note,modal){let addYoutube,addImage,addLink,postButton,cancelButton,columnIdentifier=note.closest(".board_column").find(".mod_board_column_name").text(),modalRoot=modal.getRoot();if(note.data("ident")){var noteIdentifier=textIdentifierForNote(note);postButton=strings.aria_postedit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),cancelButton=strings.aria_canceledit.replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addYoutube=strings.aria_addmedia.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addImage=strings.aria_addmedia.replace("{type}",strings.option_image).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier),addLink=strings.aria_addmedia.replace("{type}",strings.option_link).replace("{column}",columnIdentifier).replace("{post}",noteIdentifier)}else postButton=strings.aria_postnew.replace("{column}",columnIdentifier),cancelButton=strings.aria_cancelnew.replace("{column}",columnIdentifier),addYoutube=strings.aria_addmedianew.replace("{type}",strings.option_youtube).replace("{column}",columnIdentifier),addImage=strings.aria_addmedianew.replace("{type}",strings.option_image).replace("{column}",columnIdentifier),addLink=strings.aria_addmedianew.replace("{type}",strings.option_link).replace("{column}",columnIdentifier);1==mediaSelection&&(modalRoot.find(".mod_board_attachment_button.youtube_button").attr("aria-label",addYoutube),modalRoot.find(".mod_board_attachment_button.youtube_button").attr("title",addYoutube),modalRoot.find(".mod_board_attachment_button.image_button").attr("aria-label",addImage),modalRoot.find(".mod_board_attachment_button.image_button").attr("title",addImage),modalRoot.find(".mod_board_attachment_button.link_button").attr("aria-label",addLink),modalRoot.find(".mod_board_attachment_button.link_button").attr("title",addLink));let button=modalRoot.find(modal.getActionSelector("save"));button&&button.attr("aria-label",postButton),button=modalRoot.find(modal.getActionSelector("cancel")),button&&button.attr("aria-label",cancelButton)}(note,modal),modal.show(),modal})).catch(_notification.default.exception),modal})).catch(_notification.default.exception)},fullScreenNote=(ident,notecontent)=>{const heading=getNoteHeadingForNote(notecontent).html(),modalBody=(0,_jquery.default)(document.createElement("div"));modalBody.addClass("mod_board_note_content");const text=getNoteTextForNote(notecontent);text&&modalBody.append(text.clone());const preview=(note=notecontent,(0,_jquery.default)(note).find(".mod_board_preview"));var note;preview&&modalBody.append(preview.clone());const commentArea=(0,_jquery.default)(document.createElement("div"));commentArea.attr("data-region","comment-area"),modalBody.append(commentArea),_comments.default.fetchFor(ident,commentArea),_modal_factory.default.create({type:_modal_factory.default.types.CANCEL,title:heading,body:modalBody}).then((function(modal){return modal.setLarge(),modal.show(),modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal}),this).catch(_notification.default.exception)},init=function(){serviceCall("get_board",{id:board.id,ownerid:ownerId},(function(columns){if(columns)for(var index in columns)addColumn(columns[index].id,columns[index].name,columns[index].locked,columns[index].notes||{},options.colours[columns[index].id%options.colours.length]);var column,newBusy;isEditor&&(column=(0,_jquery.default)('
'),newBusy=!1,column.append('
'),handleAction(column.find(".newcolumn"),(function(){newBusy||(newBusy=!0,serviceCall("add_column",{boardid:board.id,name:strings.default_column_heading},(function(result){addColumn(result.id,strings.default_column_heading,!1,{},selectHeadingColour()),lastHistoryId=result.historyid,newBusy=!1}),(function(){newBusy=!1})))})),(0,_jquery.default)(".mod_board").append(column)),lastHistoryId=board.historyid,isEditor&&(updateSortable(),columnSorting()),updateBoard()}))},stringsInfo=[];for(var string in strings)stringsInfo.push({key:string,component:"mod_board"});_jquery.default.when((0,_str.get_strings)(stringsInfo)).done((function(results){var index=0;for(string in strings)strings[string]=results[index++];init()}))},_jquery=_interopRequireDefault(_jquery),_ajax=_interopRequireDefault(_ajax),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification),_fragment=_interopRequireDefault(_fragment),_comments=_interopRequireDefault(_comments),_movenotesdialog=_interopRequireDefault(_movenotesdialog),_movecolumnsdialog=_interopRequireDefault(_movecolumnsdialog);const isAriaTriggerKey=function(key){return 13==key||32==key},encodeText=function(rawText){return(0,_jquery.default)("
").text(rawText).html()},decodeText=function(encodedText){return(0,_jquery.default)("
").html(encodedText).text()},handleAction=function(elem,callback){return elem.on("click keypress",(function(e){if("keypress"==e.type){if(!isAriaTriggerKey(e.keyCode))return;e.preventDefault()}callback(),e.preventDefault()}))};return _exports.default})); //# sourceMappingURL=board.min.js.map \ No newline at end of file diff --git a/amd/build/board.min.js.map b/amd/build/board.min.js.map index c7ad6b3..56e92d4 100755 --- a/amd/build/board.min.js.map +++ b/amd/build/board.min.js.map @@ -1 +1 @@ -{"version":3,"file":"board.min.js","sources":["../src/board.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle the board.\n *\n * @author Karen Holland \n * @copyrigt 2021 Brickfield Education Labs \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from \"jquery\";\nimport {get_strings as getStrings, get_string as getString} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport ModalFactory from \"core/modal_factory\";\nimport ModalEvents from \"core/modal_events\";\nimport Notification from \"core/notification\";\nimport \"mod_board/jquery.editable.amd\";\nimport \"mod_board/jquery.sortable.amd\";\nimport Fragment from \"core/fragment\";\nimport Comments from \"mod_board/comments\";\nimport moveNotesDialog from \"./movenotesdialog\";\nimport moveColumnsDialog from \"./movecolumnsdialog\";\n\n/**\n * Execute a ajax call to a mod_board ajax service.\n *\n * @param {string} method\n * @param {array} args\n * @param {method} callback\n * @param {method} failcallback\n * @private\n */\nconst _serviceCall = function(method, args, callback, failcallback) {\n Ajax.call([{\n methodname: 'mod_board_' + method,\n args: args,\n done: function(data) {\n callback(data);\n },\n fail: function(error) {\n Notification.exception(error);\n if (failcallback) {\n failcallback(error);\n }\n }\n }]);\n};\n\n/**\n * Indicates if this is a keycode we want to listend to for\n * aria purposes.\n *\n * @returns {boolean}\n * @param {number} key\n */\nconst isAriaTriggerKey = function(key) {\n return key == 13 || key == 32;\n};\n\n/**\n * Encodes text into html entities.\n *\n * @param {string} rawText\n * @returns {*|jQuery}\n */\nconst encodeText = function(rawText) {\n return $('
').text(rawText).html();\n};\n\n/**\n * Decodes text from html entities.\n *\n * @param {string} encodedText\n * @returns {*|jQuery}\n */\nconst decodeText = function(encodedText) {\n return $('
').html(encodedText).text();\n};\n\n/**\n * Handler for keypress and click actions.\n *\n * @param {object} elem\n * @param {function} callback\n * @returns {*}\n */\nconst handleAction = function(elem, callback) {\n return elem.on('click keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode)) {\n e.preventDefault();\n } else {\n return;\n }\n }\n\n callback();\n e.preventDefault();\n });\n};\n\n/**\n * Setting up element edibility.\n *\n * @param {object} elem\n * @param {function} callback\n * @param {function} callBeforeOnKeyEditing\n * @returns {*}\n */\nconst handleEditableAction = function(elem, callback, callBeforeOnKeyEditing) {\n if (elem.is(':editable')) {\n throw new Error('handleEditableAction - must be called before setting the element as editable');\n }\n\n // Can't use on(edit) here because we want to do actions (save cache) before the control goes into edit mode\n return elem.on('dblclick keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode) && !elem.is(':editing')) {\n e.preventDefault();\n if (callBeforeOnKeyEditing) {\n callback();\n }\n elem.editable('open');\n if (callBeforeOnKeyEditing) {\n return;\n }\n } else {\n return;\n }\n }\n\n callback();\n });\n};\n\n/**\n * The default function of the module, which does the setup of the page.\n *\n * @param {object} settings\n */\nexport default function(settings) {\n // An array of strings to load as a batch later.\n // Not necessary, but used to load all the strings in one ajax call.\n var strings = {\n default_column_heading: '',\n post_button_text: '',\n cancel_button_text: '',\n remove_note_title: '',\n remove_note_text: '',\n remove_column_title: '',\n note_changed_title: '',\n note_changed_text: '',\n note_deleted_text: '',\n rate_note_title: '',\n rate_note_text: '',\n rate_remove_note_text: '',\n Ok: '',\n delete: '',\n Cancel: '',\n warning: '',\n modal_title_new: '',\n modal_title_edit: '',\n option_youtube: '',\n option_image: '',\n option_link: '',\n\n aria_newcolumn: '',\n aria_newpost: '',\n aria_deletecolumn: '',\n aria_movecolumn: '',\n aria_deletepost: '',\n aria_movepost: '',\n aria_editpost: '',\n aria_addmedia: '',\n aria_addmedianew: '',\n aria_deleteattachment: '',\n aria_postedit: '',\n aria_canceledit: '',\n aria_postnew: '',\n aria_cancelnew: '',\n aria_ratepost: '',\n\n invalid_file_extension: '',\n invalid_file_size_min: '',\n invalid_file_size_max: '',\n\n invalid_youtube_url: '',\n };\n\n // Json decode the strings from the settings.\n var options = JSON.parse(settings.settings) || {};\n var board = options.board || {};\n var contextid = options.contextid;\n\n const MEDIA_SELECTION_BUTTONS = 1,\n ATTACHMENT_VIDEO = 1,\n ATTACHMENT_IMAGE = 2,\n ATTACHMENT_LINK = 3,\n SORTBY_DATE = 1,\n SORTBY_RATING = 2,\n SORTBY_NONE = 3;\n\n var reloadTimer = null,\n lastHistoryId = null,\n isEditor = options.isEditor || false,\n usersCanEdit = options.usersCanEdit,\n userId = parseInt(options.userId) || -1,\n userFullname = options.userFullname,\n ownerId = parseInt(options.ownerId),\n mediaSelection = options.mediaselection || MEDIA_SELECTION_BUTTONS,\n editingNote = 0,\n isReadOnlyBoard = options.readonly || false,\n showauthorofnote = options.showauthorofnote || false,\n allowshowauthorofnoteonboard = options.allowshowauthorofnoteonboard || false,\n ratingenabled = options.ratingenabled,\n sortby = options.sortby || SORTBY_DATE,\n editModal = null,\n enableblanktarget = (parseInt(options.enableblanktarget) === 1);\n\n /**\n * Helper method to make calls to mod_board external services.\n *\n * @param {string} method\n * @param {array} args\n * @param {function} callback\n * @param {function} failcallback\n */\n var serviceCall = function(method, args, callback, failcallback) {\n if (method !== 'board_history') {\n stopUpdating();\n }\n _serviceCall(method, args, function() {\n if (callback) {\n callback.apply(null, arguments);\n }\n if (method !== 'board_history' && method != 'get_board') {\n updateBoard(true);\n }\n }, failcallback);\n };\n\n /**\n * Returns the jquery element of a given note identifier.\n *\n * @param {number} ident\n * @returns {jQuery}\n */\n var getNote = function(ident) {\n return $(\".board_note[data-ident='\" + ident + \"']\");\n };\n\n /**\n * Returns the jquery element of the note text for the given note element.\n *\n * @method getNoteTextForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteTextForNote = function(note) {\n return $(note).find(\".mod_board_note_text\");\n };\n\n /**\n * Returns the jquery element of the preview for the given note element.\n *\n * @method getNotePreviewForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNotePreviewForNote = (note) => {\n return $(note).find(\".mod_board_preview\");\n };\n\n\n /**\n * Returns the jquery element of the note heading for the given note element.\n *\n * @method getNoteHeadingForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteHeadingForNote = function(note) {\n return $(note).find(\".mod_board_note_heading\");\n };\n\n /**\n * Returns the jquery element of the note border for the given note element.\n *\n * @method getNoteBorderForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteBorderForNote = function(note) {\n return $(note).find(\".mod_board_note_border\");\n };\n\n /**\n * Gets a jquery node for the attachments of a given note.\n *\n * @method getNoteAttachmentsForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteAttachmentsForNote = function(note) {\n return $(note).find(\".mod_board_note_attachment\");\n };\n\n /**\n * Creates text identifier for a given node.\n *\n * @method textIdentifierForNote\n * @param {object} note\n * @returns {null|*|jQuery}\n */\n var textIdentifierForNote = function(note) {\n var noteText = getNoteTextForNote(note).html(),\n noteHeading = getNoteHeadingForNote(note).html(),\n noteAttachment = attachmentDataForNote(note);\n\n if (noteHeading.length > 0) {\n return noteHeading;\n }\n if (noteText.length > 0) {\n return noteText.replace(//gi, \" \").replace(/\\n/g, \" \").split(/\\s+/).slice(0, 5).join(\" \");\n }\n if (noteAttachment.info && noteAttachment.info.length > 0) {\n return noteAttachment.info;\n }\n return null;\n };\n\n /**\n * Update the Aria info for a given note id.\n *\n * @method updateNoteAria\n * @param {number} noteId\n */\n var updateNoteAria = function(noteId) {\n var note = getNote(noteId),\n columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text();\n\n if (noteId) { // New post\n var noteIdentifier = textIdentifierForNote(note),\n deleteNoteString = strings.aria_deletepost.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n\n note.find('.delete_note').attr('aria-label', deleteNoteString).attr('title', deleteNoteString);\n\n var moveNoteString = strings.aria_movepost.replace('{post}', noteIdentifier);\n note.find('.move_note').attr('aria-label', moveNoteString).attr('title', moveNoteString);\n\n var editNoteString = strings.aria_editpost.replace('{post}', noteIdentifier);\n note.find('.edit_note').attr('aria-label', editNoteString).attr('title', editNoteString);\n\n note.find('.mod_board_rating').attr('aria-label', strings.aria_ratepost.replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier));\n note.find('.note_ariatext').html(noteIdentifier);\n }\n\n };\n\n /**\n * Update the Aria information for a given column id.\n *\n * @method updateColumnAria\n * @param {number} columnId\n */\n var updateColumnAria = function(columnId) {\n var column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n newNoteString = strings.aria_newpost.replace('{column}', columnIdentifier),\n moveColumnString = strings.aria_movecolumn.replace('{column}', columnIdentifier),\n deleteColumnString = strings.aria_deletecolumn.replace('{column}', columnIdentifier);\n column.find('.newnote').attr('aria-label', newNoteString).attr('title', newNoteString);\n column.find('.mod_column_move').attr('aria-label', moveColumnString).attr('title', moveColumnString);\n column.find('.delete_column').attr('aria-label', deleteColumnString).attr('title', deleteColumnString);\n\n column.find(\".board_note\").each(function(index, note) {\n updateNoteAria($(note).data('ident'));\n });\n };\n\n /**\n * Stop the current note editing process.\n *\n * @method stopNoteEdit\n */\n var stopNoteEdit = function() {\n if (!editingNote) {\n getNote(0).remove();\n return;\n }\n\n var note = getNote(editingNote);\n\n if (note) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n }\n\n editingNote = 0;\n };\n\n /**\n * Start the editing of a particular note, by identifier.\n *\n * @method startNoteEdit\n * @param {number} ident\n */\n var startNoteEdit = function(ident) {\n\n if (editingNote) {\n if (editingNote == ident) {\n return;\n }\n stopNoteEdit();\n }\n\n if (ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n var note = getNote(ident);\n if (note) {\n showModalForm(note);\n\n if (ident) {\n editingNote = ident;\n }\n }\n };\n\n /**\n * Delete a given note, by identifier.\n *\n * @method deleteNote\n * @param {number} ident\n */\n var deleteNote = function(ident) {\n Notification.confirm(\n strings.remove_note_title, // Are you sure?\n strings.remove_note_text, // This will effect others.\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_note', { id: ident }, function (result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n let note = getNote(ident);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n }\n });\n }\n );\n };\n\n /**\n * This function gets a board column as a jQuery element.\n * @param {number} columnID The column ID.\n * @returns {jQuery}\n */\n const getColumn = (columnID) => {\n return $(`.board_column[data-ident='${columnID}'] .board_column_content`);\n };\n\n const sortAfterDelete = (columnID, sortorder) => {\n let column = getColumn(columnID);\n let elements = column.children().filter((_, element) => {\n return parseInt($(element).data('sortorder')) > parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so - 1);\n });\n };\n\n /**\n * Rate (star) a give note, by identifier.\n *\n * @method rateNote\n * @param {number} ident\n */\n var rateNote = function(ident) {\n if (!ratingenabled) {\n return;\n }\n if (isReadOnlyBoard) {\n return;\n }\n\n var note = getNote(ident),\n rating = note.find('.mod_board_rating');\n if (rating.data('disabled')) {\n return;\n }\n rating.data('disabled', true);\n\n serviceCall('can_rate_note', {id: ident}, function(result) {\n if (result.canrate) {\n const rateRemoveText = result.hasrated ? strings.rate_remove_note_text : strings.rate_note_text;\n Notification.confirm(\n strings.rate_note_title,\n rateRemoveText, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n serviceCall('rate_note', {id: ident}, function(result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n rating.html(` ${result.rating} `);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n rating.data('disabled', false);\n });\n }\n ).then(function(rateModal) {\n // Do this here, because it catches both cancel clicks, or someone clicking the X.\n rateModal.getRoot().on(ModalEvents.hidden, function() {\n rating.data('disabled', false);\n });\n });\n }\n });\n };\n\n /**\n * Update the attachment information of a note.\n *\n * @method attachmentTypeChanged\n * @param {object} note\n */\n var attachmentTypeChanged = function(note) {\n var noteAttachment = getNoteAttachmentsForNote(note),\n type = noteAttachment.find('.mod_board_type').val(),\n attachmentInfo = noteAttachment.find('.info'),\n attachmentUrl = noteAttachment.find('.url'),\n attachmentFile = noteAttachment.find('.mod_board_file');\n\n if (type > \"0\") {\n attachmentInfo.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_info']);\n attachmentUrl.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_url']);\n\n attachmentInfo.show();\n if (type == ATTACHMENT_IMAGE && FileReader) {\n attachmentFile.show();\n attachmentUrl.hide();\n } else {\n attachmentFile.hide();\n attachmentUrl.show();\n }\n } else {\n attachmentInfo.hide();\n attachmentUrl.hide();\n attachmentFile.hide();\n\n attachmentInfo.val('');\n attachmentUrl.val('');\n\n }\n };\n\n /**\n * Set the attachment of a note.\n *\n * @method setAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var setAttachment = function(note, attachment) {\n var noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment) {\n if (!attachment) {\n attachment = {type: \"0\"};\n } else {\n attachment.type += \"\";// Just in case\n }\n var attType = noteAttachment.find('.mod_board_type');\n attType.val(attachment.type ? attachment.type : \"0\");\n if (attType.val() > \"0\") {\n noteAttachment.find('.info').val(decodeText(attachment.info));\n noteAttachment.find('.url').val(decodeText(attachment.url));\n }\n attachmentTypeChanged(note, attachment);\n }\n previewAttachment(note, attachment);\n };\n\n /**\n * Returns an object with various information about a note's attachment.\n *\n * @method attachmentDataForNote\n * @param {object} note\n * @returns {{filename: null, filecontents: null, type: number, url: null, info: null}}\n */\n var attachmentDataForNote = function(note) {\n var attachment = {type: 0, info: null, url: null, filename: null, filecontents: null},\n noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment.length) {\n attachment.type = noteAttachment.find('.mod_board_type').val();\n attachment.info = encodeText(noteAttachment.find('.info').val());\n attachment.url = encodeText(noteAttachment.find('.url').val());\n var fileElem = noteAttachment.find('.mod_board_file>input');\n if (fileElem.data('filename')) {\n attachment.filename = fileElem.data('filename');\n attachment.filecontents = fileElem.data('filecontents');\n }\n }\n if ((!attachment.info || !attachment.info.length) && (!attachment.url || !attachment.url.length) &&\n (!attachment.filename)) {\n attachment.type = 0;\n }\n\n return attachment;\n };\n\n /**\n * Get the string type of a attachment type number.\n *\n * @method attachmentTypeToString\n * @param {number} type\n * @returns {string|null}\n */\n var attachmentTypeToString = function(type) {\n switch (type) {\n case \"1\": return 'youtube';\n case \"2\": return 'image';\n case \"3\": return 'link';\n default: return null;\n }\n };\n\n /**\n * This parses a youtube video ID from a URL. We can use this ID to\n * construct the embed URL.\n * @param {string} url The URL entered to the modal.\n * @returns {string | null} The youtube embed URL or null.\n */\n const getEmbedUrl = (url) => {\n // Thanks for the regex from: https://gist.github.com/rodrigoborgesdeoliveira/987683cfbfcc8d800192da1e73adc486.\n let regex = /(\\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/;\n let videoID = url.match(regex);\n if (!videoID || videoID[2] === undefined || videoID[2].length !== 11) {\n return null;\n }\n return `https://www.youtube-nocookie.com/embed/${videoID[2]}`;\n };\n\n /**\n * Display the attachment preview for a note.\n *\n * @method previewAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var previewAttachment = function(note, attachment) {\n var elem = note.find('.mod_board_preview');\n if (!attachment) {\n attachment = attachmentDataForNote(note);\n }\n\n if (!getNoteTextForNote(note).html().length) {\n elem.addClass('mod_board_notext');\n } else {\n elem.removeClass('mod_board_notext');\n }\n\n elem.removeClass('wrapper_youtube');\n elem.removeClass('wrapper_image');\n elem.removeClass('wrapper_url');\n if (attachment.filename && parseInt(attachment.type) == ATTACHMENT_IMAGE) { // Before uploading\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n } else if (attachment.url) {\n const blanktarget = enableblanktarget ? ' target=\"_blank\"' : '';\n switch (parseInt(attachment.type)) {\n case ATTACHMENT_VIDEO: { // Youtube\n let url = getEmbedUrl(attachment.url);\n if (url === null) {\n elem.html(strings.invalid_youtube_url);\n } else {\n elem.html('');\n elem.addClass('wrapper_youtube').addClass('position-relative');\n }\n elem.show();\n }\n break;\n case ATTACHMENT_IMAGE: // Image\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n break;\n case ATTACHMENT_LINK: // Url\n elem.html('' +\n (attachment.info || attachment.url) + '');\n elem.addClass('wrapper_url');\n elem.show();\n break;\n default:\n elem.html('');\n elem.hide();\n }\n } else {\n elem.html('');\n elem.hide();\n }\n };\n\n /**\n * Add a new note with the given information.\n *\n * @method addNote\n * @param {number} columnid\n * @param {number} ident\n * @param {string} heading\n * @param {string} content\n * @param {object} attachment\n * @param {object} owner the owner of the note containing the userid as id and the owner fullname\n * @param {number} sortorder\n * @param {string} rating\n */\n var addNote = function(columnid, ident, heading, content, attachment, owner, sortorder, rating) {\n var ismynote = owner.id == userId || !ident;\n var iseditable = isEditor || (ismynote && !isReadOnlyBoard);\n\n if (!ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n // Making space for this note if necessary in the sort order.\n if (sortby == SORTBY_NONE) {\n let children = $(`.board_column[data-ident='${columnid}'] .board_column_content`).children();\n let elements = children.filter((_, element) => {\n return parseInt($(element).data('sortorder')) >= parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so + 1);\n });\n }\n\n var note = $('
');\n if (ismynote) {\n note.addClass('mod_board_mynote');\n }\n if (iseditable) {\n note.addClass('mod_board_editablenote');\n }\n if (!ismynote && !iseditable) {\n note.addClass('mod_board_nosort');\n }\n\n var notecontent = $('
'),\n notecontrols = $('
'),\n noteHeading = $('
' + (heading ? heading : '') + '
'),\n noteAuthorusername = $(''),\n noteBorder = $('
'),\n noteText = $('
' + (content ? content : '') + '
'),\n noteAriaText = $('
'),\n attachmentPreview = $('
');\n\n if (allowshowauthorofnoteonboard == true && showauthorofnote == true) {\n let fullname = '';\n if (ismynote) {\n // Use the Name of the user itself. We do not need to get this information from somewhere else.\n fullname = userFullname;\n } else {\n fullname = owner.fullname;\n }\n\n noteAuthorusername = '
' +\n ' ' +\n '' +\n fullname +\n '' +\n '
' ;\n }\n\n notecontent.append(noteHeading);\n notecontent.append(noteAuthorusername);\n notecontent.append(noteBorder);\n notecontent.append(noteText);\n notecontent.append(noteAriaText);\n\n notecontent.append(attachmentPreview);\n note.append(notecontent);\n\n var columnContent = $('.board_column[data-ident=' + columnid + '] .board_column_content');\n\n var beginEdit = () => {\n startNoteEdit(ident);\n };\n\n if (ident) {\n if (ratingenabled) {\n note.addClass('mod_board_rateablenote');\n var rateElement = $(`
${rating}
`);\n\n handleAction(rateElement, () => {\n rateNote(ident);\n });\n notecontrols.append(rateElement);\n }\n\n if (iseditable) {\n var removeElement = $('
');\n handleAction(removeElement, () => {\n deleteNote(ident);\n });\n\n notecontrols.append(removeElement);\n\n if (usersCanEdit == 1 || isEditor) {\n var moveElement = $('
');\n notecontrols.append(moveElement);\n moveNotesDialog.init(ownerId, moveNote);\n }\n\n var editElement = $('
');\n notecontrols.append(editElement);\n handleAction(editElement, () => {\n beginEdit();\n });\n updateSortable();\n setAttachment(note, attachment);\n } else {\n previewAttachment(note, attachment);\n }\n\n note.append(notecontrols);\n\n handleAction(notecontent, () => fullScreenNote(ident, notecontent));\n\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n\n var lastOne = columnContent.find(\".board_note\").last();\n\n if (lastOne.length) {\n note.insertAfter(lastOne);\n } else {\n columnContent.prepend(note);\n }\n } else {\n $('.board_column[data-ident=' + columnid + '] .board_column_newcontent').append(note);\n // This is effectively a note placeholder. So we don't need to show it.\n note.hide();\n beginEdit();\n }\n };\n\n /**\n * Add a new column.\n *\n * @method addColumn\n * @param {object} ident\n * @param {string} name\n * @param {bool} locked\n * @param {array} notes\n * @param {string} colour\n */\n var addColumn = function(ident, name, locked, notes, colour) {\n let headerStyle = `style=\"border-top: 10px solid #${colour}\"`;\n var iseditable = isEditor,\n nameCache = null,\n column = $(`
`),\n columnHeader = $('
'),\n columnSort = $('
'),\n columnName = $('
' + name + '
'),\n columnContent = $('
'),\n columnNewContent = $('
');\n // Only add the sort button if it makes sense.\n if (sortby != SORTBY_NONE) {\n columnHeader.append(columnSort);\n }\n columnHeader.append(columnName);\n\n if (options.hideheaders) {\n columnName.addClass('d-none');\n }\n\n columnSort.on('click', function() {\n sortNotes(columnContent, true);\n });\n\n if (iseditable) {\n column.addClass('mod_board_editablecolumn');\n const lockIcon = locked ? 'fa-lock' : 'fa-unlock';\n const lockElement = $(`
`);\n const lockstring = locked ? 'aria_column_locked' : 'aria_column_unlocked';\n getString(lockstring, 'mod_board', name).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n\n handleAction(lockElement, () => {\n const lockColumn = column.attr('data-locked') !== 'true';\n serviceCall('lock_column', {id: ident, status: lockColumn}, function(result) {\n const columnName = column.find('.mod_board_column_name').text();\n if (result.status) {\n if (lockColumn) {\n lockElement.removeClass('fa-unlock').addClass('fa-lock');\n column.attr('data-locked', 'true');\n column.find('.board_button.newnote').addClass('d-none');\n getString('aria_column_locked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n } else {\n lockElement.removeClass('fa-lock').addClass('fa-unlock');\n column.attr('data-locked', 'false');\n column.find('.board_button.newnote').removeClass('d-none');\n getString('aria_column_unlocked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n }\n lastHistoryId = result.historyid;\n updateSortable();\n }\n });\n });\n columnHeader.append(lockElement);\n\n columnHeader.addClass('icon-size-3');\n const moveElement = $('
');\n columnHeader.append(moveElement);\n moveColumnsDialog.init(moveColumn);\n var removeElement = $('
');\n handleAction(removeElement, () => {\n Notification.confirm(\n strings.remove_column_title, // Are you sure?\n getString('remove_column_text', 'mod_board', getColumnName(ident)),\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_column', {id: ident}, function(result) {\n if (result.status) {\n column.remove();\n lastHistoryId = result.historyid;\n }\n });\n }\n );\n });\n\n columnHeader.append(removeElement);\n }\n\n column.append(columnHeader);\n column.append(columnContent);\n column.append(columnNewContent);\n\n if (iseditable) {\n handleEditableAction(columnName, function() {\n nameCache = columnName.html();\n }, true);\n\n columnName.editable({\n toggleFontSize: false,\n closeOnEnter: true,\n callback: function(data) {\n if (data.content) {\n serviceCall('update_column', {id: ident, name: columnName.html()}, function(result) {\n if (!result.status) {\n columnName.html(nameCache);\n nameCache = null;\n } else {\n lastHistoryId = result.historyid;\n updateColumnAria(ident);\n }\n }, function() {\n columnName.html(nameCache);\n nameCache = null;\n });\n } else {\n columnName.html(nameCache);\n nameCache = null;\n }\n }\n });\n }\n\n if (!isReadOnlyBoard) {\n const newNoteButton = $('
' +\n '
');\n columnNewContent.append(newNoteButton);\n if (column.attr('data-locked') === 'true') {\n newNoteButton.addClass('d-none');\n }\n handleAction(columnNewContent.find('.newnote'), function() {\n // We do not need to add fullname to the owner because we use ismynote and the fullname of the actual board user.\n addNote(ident, 0, null, null, null, {id: userId}, 0, 0);\n });\n }\n\n var lastOne = $(\".mod_board .board_column_hasdata\").last();\n if (lastOne.length) {\n column.insertAfter(lastOne);\n } else {\n $(\".mod_board\").append(column);\n }\n\n if (notes) {\n for (var index in notes) {\n let sortorder = sortby == 3 ? notes[index].sortorder : notes[index].timecreated;\n\n addNote(ident, notes[index].id, notes[index].heading, notes[index].content,\n {type: notes[index].type, info: notes[index].info, url: notes[index].url},\n {id: notes[index].userid, fullname: notes[index].fullname},\n sortorder, notes[index].rating);\n }\n }\n sortNotes(columnContent);\n updateColumnAria(ident);\n if (isEditor || usersCanEdit == 1) {\n updateSortable();\n }\n if (isEditor) {\n columnSorting();\n }\n };\n\n /**\n * Gets the text name used in the heading of a column.\n * @param {number} id The ID data attribute on the column element.\n * @returns {string}\n */\n const getColumnName = (id) => {\n return $(`.board_column[data-ident='${id}']`).find('.mod_board_column_name').html();\n };\n\n /**\n * Add the new column button.\n *\n * @method addNewColumnButton\n */\n var addNewColumnButton = function() {\n var column = $('
'),\n newBusy = false;\n column.append('
');\n\n handleAction(column.find('.newcolumn'), function() {\n if (newBusy) {\n return;\n }\n newBusy = true;\n\n serviceCall('add_column', {boardid: board.id, name: strings.default_column_heading}, function(result) {\n addColumn(result.id, strings.default_column_heading, false, {}, selectHeadingColour());\n lastHistoryId = result.historyid;\n newBusy = false;\n }, function() {\n newBusy = false;\n });\n });\n\n $(\".mod_board\").append(column);\n };\n\n /**\n * This selects the next heading colour from options based on the count of the\n * current columns. Length of decremented by one as the new column button is\n * also denoted as a column.\n * @returns {string} colour hex string.\n */\n const selectHeadingColour = () => {\n let colCount = $('.board_column').length - 1;\n let colourCount = options.colours.length;\n return options.colours[colCount % colourCount];\n };\n\n /**\n * Update a note with the provided information.\n *\n * @method updateNote\n * @param {object} note\n * @param {string} heading\n * @param {object} data\n */\n var updateNote = function(note, heading, data) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n noteText.html(data.content);\n noteHeading.html(data.heading);\n setAttachment(note, data.attachment);\n updateNoteAria(data.id);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n };\n\n /**\n * Fetch and process the recent board history.\n *\n * @method processBoardHistory\n */\n var processBoardHistory = function() {\n serviceCall('board_history', {id: board.id, ownerid: ownerId, since: lastHistoryId}, function(boardhistory) {\n for (var index in boardhistory) {\n var item = boardhistory[index];\n if (item.boardid != board.id) {\n continue; // Hmm\n }\n\n var data = JSON.parse(item.content);\n if (item.action == 'add_note') {\n let sortorder = sortby == 3 ? data.sortorder : data.timecreated;\n addNote(data.columnid, data.id, data.heading, data.content, data.attachment,\n {id: item.userid}, sortorder, data.rating);\n updateNoteAria(data.id);\n sortNotes($('.board_column[data-ident=' + data.columnid + '] .board_column_content'));\n } else if (item.action == 'update_note') {\n let note = getNote(data.id),\n formModal = editModal,\n historyData = data;\n if (note) {\n let noteHeading = getNoteHeadingForNote(note);\n\n if (editingNote == data.id) {\n Notification.confirm(\n strings.note_changed_title, // Confirm.\n strings.note_changed_text, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n formModal.hide();\n updateNote(note, noteHeading, historyData);\n stopNoteEdit();\n }\n );\n } else {\n updateNote(note, noteHeading, data);\n }\n }\n } else if (item.action == 'delete_note') {\n if (editingNote == data.id) {\n Notification.alert(strings.warning, strings.note_deleted_text);\n stopNoteEdit();\n }\n let note = getNote(data.id);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n\n } else if (item.action == 'add_column') {\n addColumn(data.id, data.name, false, {}, selectHeadingColour());\n } else if (item.action == 'move_column') {\n const board = $('.mod_board');\n data.sortorder.forEach(column => {\n const columnElement = board.find(`.board_column[data-ident='${column}']`);\n columnElement.detach().appendTo(board);\n });\n } else if (item.action == 'update_column') {\n $(\".board_column[data-ident='\" + data.id + \"'] .mod_board_column_name\").html(data.name);\n updateColumnAria(data.id);\n } else if (item.action == 'lock_column') {\n $(\".board_column[data-ident='\" + data.id + \"']\").attr(\"data-locked\", data.locked);\n if (data.locked) {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').addClass('d-none');\n } else {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').removeClass('d-none');\n }\n updateSortable();\n } else if (item.action == 'delete_column') {\n var column = $(\".board_column[data-ident='\" + data.id + \"']\");\n if (editingNote && column.find('.board_note[data-ident=\"' + editingNote + '\"]').length) {\n stopNoteEdit();\n }\n column.remove();\n } else if (item.action == 'rate_note') {\n var note = getNote(data.id);\n note.find('.mod_board_rating').html(data.rating);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n lastHistoryId = item.id;\n }\n\n updateBoard();\n });\n };\n\n /**\n * Trigger a board update.\n *\n * @method updateBoard\n * @param {boolean} instant\n */\n var updateBoard = function(instant) {\n if (instant) {\n processBoardHistory();\n } else if (options.history_refresh > 0) {\n if (reloadTimer) {\n stopUpdating();\n }\n reloadTimer = setTimeout(processBoardHistory, options.history_refresh * 1000);\n }\n };\n\n /**\n * Stop/prevent the board reload timer from firing.\n *\n * @method stopUpdating\n */\n var stopUpdating = function() {\n clearTimeout(reloadTimer);\n reloadTimer = null;\n };\n\n /**\n * Sort a set of notes.\n *\n * @sortNotes\n * @param {string} content\n * @param {boolean} toggle\n */\n var sortNotes = function(content, toggle) {\n var sortCol = $(content).parent().find('.mod_board_column_sort'),\n direction = $(content).data('sort');\n if (!direction) {\n if (sortby == SORTBY_RATING) {\n direction = 'desc';\n } else {\n direction = 'asc';\n }\n }\n if (toggle) {\n direction = direction == 'asc' ? 'desc' : 'asc';\n }\n\n if (direction == 'asc') {\n sortCol.removeClass('fa-angle-down');\n sortCol.addClass('fa-angle-up');\n } else {\n sortCol.removeClass('fa-angle-up');\n sortCol.addClass('fa-angle-down');\n }\n $(content).data('sort', direction);\n\n var desc,\n asc;\n if (sortby == SORTBY_DATE) {\n desc = function(a, b) {\n return $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_RATING) {\n desc = function(a, b) {\n return $(b).find('.mod_board_rating').text() - $(a).find('.mod_board_rating').text() ||\n $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).find('.mod_board_rating').text() - $(b).find('.mod_board_rating').text() ||\n $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_NONE) {\n let sortElements = (a, b) => {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n $('> .board_note', $(content)).sort(sortElements).appendTo($(content));\n return;\n }\n\n $('> .board_note', $(content)).sort(direction === 'asc' ? asc : desc).appendTo($(content));\n\n };\n\n /**\n * Update sorting of sortable content.\n *\n * @method updateSortable\n */\n var updateSortable = function() {\n let fromColumnID;\n $(\".board_column[data-locked='false'] .board_column_content\").sortable({\n connectWith: \".board_column[data-locked='false'] .board_column_content\",\n cancel: \".mod_board_nosort\",\n handle: \".move_note\",\n start: function(_, ui) {\n fromColumnID = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n var note = $(ui.item),\n tocolumn = note.closest('.board_column'),\n elem = $(this),\n noteid = note.data('ident'),\n columnid = tocolumn.data('ident');\n let columnElements = tocolumn.find('.board_column_content').children();\n let sortorder = columnElements.index($(`.board_note[data-ident=${noteid}]`));\n let payload = {\n id: noteid,\n columnid: columnid,\n ownerid: ownerId,\n sortorder: sortorder\n };\n moveNote(fromColumnID, payload, elem);\n }\n });\n };\n\n /**\n * Move a note to a new position / column.\n *\n * @param {Int} fromColumnID The column the note is being moved from.\n * @param {Object} payload The payload to send to the server.\n * @param {Domnode} elem The element clicked to trigger the move.\n */\n const moveNote = (fromColumnID, payload, elem) => {\n updateSortOrders(fromColumnID, payload.columnid, payload.id, payload.sortorder);\n\n serviceCall('move_note', payload, (result) => {\n if (result.status) {\n lastHistoryId = result.historyid;\n updateNoteAria(payload.id);\n updateBoard();\n sortNotes($(`.board_column[data-ident=${payload.columnid}] .board_column_content`));\n } else {\n if (elem) {\n elem.sortable('cancel');\n }\n }\n });\n };\n\n /**\n * Enable column sorting\n */\n const columnSorting = () => {\n let movingColumnId;\n $(\".mod_board\").sortable({\n connectWith: \".mod_board\",\n axis: \"x\",\n containment: \".mod_board_wrapper\",\n cancel: \".mod_board_nosort\",\n handle: \".mod_column_move\",\n start: function(_, ui) {\n movingColumnId = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n let column = $(ui.item);\n let columns = $(\".mod_board\").find('.board_column');\n let sortorder = columns.index(column);\n let payload = {\n id: movingColumnId,\n sortorder: sortorder\n };\n moveColumn(payload);\n }\n });\n };\n\n /**\n * Move a column to a new position.\n *\n * @param {Object} payload The payload to send to the server.\n */\n const moveColumn = (payload) => {\n serviceCall('move_column', payload, false);\n };\n\n /**\n * Updates the inline data attributes necessary for rendering the lists\n * in the correct sort order. Note: the data attribute values updated by\n * jQuery are not reflected in DOM inspection but are still set.\n * @param {number} fromColumnID The column ID of the column to sort.\n * @param {number} toColumnID The column ID of the column to sort.\n * @param {number} noteID The note ID that was moved.\n * @param {number} newSortOrder The new position of the note sort order.\n */\n const updateSortOrders = (fromColumnID, toColumnID, noteID, newSortOrder) => {\n let toColumn = $(`.board_column[data-ident=${toColumnID}] .board_column_content`);\n let movedNote = $(`.board_note[data-ident=${noteID}]`);\n let oldSortOrder = movedNote.data('sortorder');\n // Check whether it is the same column and then increment or decrement notes above or below\n // then set sortorder according to whether the sortorder has moved up or down.\n let toChildren = toColumn.children();\n if (fromColumnID == toColumnID) {\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (oldSortOrder < newSortOrder) {\n if (sortOrder <= newSortOrder && sortOrder >= oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n } else if (oldSortOrder > newSortOrder) {\n if (sortOrder >= newSortOrder && sortOrder <= oldSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n }\n });\n } else {\n let fromColumn = $(`.board_column[data-ident=${fromColumnID}] .board_column_content`);\n let fromChildren = fromColumn.children();\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder >= newSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n });\n fromChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder > oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n });\n }\n movedNote.data('sortorder', newSortOrder);\n };\n\n /**\n * Get the body fragment for the modal form.\n *\n * @param {number} noteid\n * @param {number} columnid\n * @param {number} ownerId\n * @returns {Deferred|*}\n */\n var getBody = function(noteid, columnid, ownerId) {\n // Get the content of the modal.\n var params = {noteid: noteid, columnid: columnid, ownerid: ownerId};\n return Fragment.loadFragment('mod_board', 'note_form', contextid, params);\n };\n\n /**\n * Setup the aria labels for the modal.\n *\n * @param {object} note\n * @param {object} modal\n */\n var updateModalAria = function(note, modal) {\n let columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text(),\n addYoutube,\n addImage,\n addLink,\n postButton,\n cancelButton,\n modalRoot = modal.getRoot();\n\n if (note.data('ident')) {\n // Is a note update.\n var noteIdentifier = textIdentifierForNote(note);\n\n postButton = strings.aria_postedit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n cancelButton = strings.aria_canceledit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n addYoutube = strings.aria_addmedia.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addImage = strings.aria_addmedia.replace('{type}', strings.option_image).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addLink = strings.aria_addmedia.replace('{type}', strings.option_link).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n } else {\n // Note is new.\n postButton = strings.aria_postnew.replace('{column}', columnIdentifier);\n cancelButton = strings.aria_cancelnew.replace('{column}', columnIdentifier);\n addYoutube = strings.aria_addmedianew.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier);\n addImage = strings.aria_addmedianew.replace('{type}', strings.option_image).replace('{column}', columnIdentifier);\n addLink = strings.aria_addmedianew.replace('{type}', strings.option_link).replace('{column}', columnIdentifier);\n }\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('aria-label', addYoutube);\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('title', addYoutube);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('aria-label', addImage);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('title', addImage);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('aria-label', addLink);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('title', addLink);\n }\n\n let button = modalRoot.find(modal.getActionSelector('save'));\n if (button) {\n button.attr('aria-label', postButton);\n }\n button = modalRoot.find(modal.getActionSelector('cancel'));\n if (button) {\n button.attr('aria-label', cancelButton);\n }\n };\n\n /**\n * Displays the modal form to edit a note.\n *\n * @param {object} note\n */\n var showModalForm = function(note) {\n let noteId = 0,\n columnId = note.data('column'),\n column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n title;\n\n if (note.data('ident')) {\n noteId = note.data('ident');\n title = strings.modal_title_edit.replace('{column}', columnIdentifier);\n } else {\n title = strings.modal_title_new.replace('{column}', columnIdentifier);\n }\n\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: getBody(noteId, columnId, ownerId),\n large: true,\n removeOnClose: true\n }).then(function(modal) {\n // Use the body promise so we know body content is loaded.\n modal.getBodyPromise().then(function () {\n let saveInProgress = false;\n editModal = modal;\n modal.setLarge();\n modal.setSaveButtonText(strings.post_button_text);\n modal.setButtonText('cancel', strings.cancel_button_text);\n\n modal.getRoot().on(ModalEvents.hidden, function () {\n stopNoteEdit();\n if (!note.data('ident')) {\n note.remove();\n }\n });\n\n modal.getRoot().on(ModalEvents.save, function (e) {\n e.preventDefault();\n modal.getRoot().find('form').submit();\n });\n\n var changeEvent = document.createEvent('HTMLEvents');\n changeEvent.initEvent('change', true, true);\n\n modal.getRoot().on('submit', 'form', function (e) {\n e.preventDefault();\n\n // Prevent multiple form submissions from being sent.\n if (saveInProgress) {\n return;\n }\n saveInProgress = true;\n\n // First, make sure the native html5 validity checks are run.\n let valid = modal.getRoot().find('form').get(0).reportValidity();\n if (!valid) {\n saveInProgress = false;\n return;\n }\n\n // Prompt all inputs to run their validation functions.\n // Normally this would happen when the form is submitted, but\n // since we aren't submitting the form normally we need to run client side\n // validation.\n modal.getRoot().find(':input').each(function (index, element) {\n element.dispatchEvent(changeEvent);\n });\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n var invalid = $.merge(\n modal.getRoot().find('[aria-invalid=\"true\"]'),\n modal.getRoot().find('.error'),\n modal.getRoot().find(':invalid')\n );\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n saveInProgress = false;\n return;\n }\n\n var formData = JSON.stringify(modal.getRoot().find('form').serialize());\n serviceCall('submit_form', {contextid: contextid, jsonformdata: formData}, function (result) {\n if (result.status) {\n if (result.action == 'insert') {\n // Added a new note.\n lastHistoryId = result.historyid;\n note.remove();\n addNote(columnId, result.note.id, result.note.heading, result.note.content,\n {type: result.note.type, info: result.note.info, url: result.note.url},\n {id: result.note.userid}, result.note.timecreated, result.note.rating);\n sortNotes($('.board_column[data-ident=' + columnId + '] .board_column_content'));\n updateNoteAria(result.note.id);\n } else {\n // Updated existing note.\n lastHistoryId = result.historyid;\n getNoteTextForNote(note).html(result.note.content);\n getNoteHeadingForNote(note).html(result.note.heading);\n updateNoteAria(result.note.id);\n setAttachment(note, {\n type: result.note.type,\n info: result.note.info, url: result.note.url\n });\n }\n stopNoteEdit();\n\n // Clear the form changed checker.\n Y.use('moodle-core-formchangechecker', function() {\n M.core_formchangechecker.reset_form_dirty_state();\n });\n\n modal.destroy();\n } else {\n modal.destroy();\n }\n });\n\n });\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n // First hide the select menu.\n modal.getRoot().find('#fitem_id_mediatype').hide();\n\n let mediaSelect = modal.getRoot().find('#fitem_id_mediatype select'),\n ytButton = modal.getRoot().find('.mod_board_attachment_button.youtube_button'),\n pictureButton = modal.getRoot().find('.mod_board_attachment_button.image_button'),\n linkButton = modal.getRoot().find('.mod_board_attachment_button.link_button'),\n updateMediaButtons = function() {\n ytButton.removeClass('selected');\n pictureButton.removeClass('selected');\n linkButton.removeClass('selected');\n switch (mediaSelect.val()) {\n case (\"1\"):\n ytButton.addClass('selected');\n break;\n case (\"2\"):\n pictureButton.addClass('selected');\n break;\n case (\"3\"):\n linkButton.addClass('selected');\n break;\n }\n };\n\n updateMediaButtons();\n handleAction(ytButton, function() {\n if (mediaSelect.val() === \"1\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(1);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(pictureButton, function() {\n if (mediaSelect.val() === \"2\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(2);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(linkButton, function() {\n if (mediaSelect.val() === \"3\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(3);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n } else {\n modal.getRoot().find('#fitem_id_mediabuttons').hide();\n }\n\n updateModalAria(note, modal);\n modal.show();\n\n return modal;\n }).catch(Notification.exception);\n return modal;\n }).catch(Notification.exception);\n };\n\n /**\n * Show the note in a modal\n * @param {Int} ident The note id\n * @param {Object} notecontent The note content\n */\n var fullScreenNote = (ident, notecontent) => {\n const heading = getNoteHeadingForNote(notecontent).html();\n const modalBody = $(document.createElement('div'));\n modalBody.addClass('mod_board_note_content');\n const text = getNoteTextForNote(notecontent);\n if (text) {\n modalBody.append(text.clone());\n }\n const preview = getNotePreviewForNote(notecontent);\n if (preview) {\n modalBody.append(preview.clone());\n }\n\n // Adds the comments to a note.\n const commentArea = $(document.createElement('div'));\n commentArea.attr('data-region', 'comment-area');\n modalBody.append(commentArea);\n Comments.fetchFor(ident, commentArea);\n\n ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: heading,\n body: modalBody,\n }).then(function(modal) {\n modal.setLarge();\n modal.show();\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function () {\n // Destroy when hidden.\n modal.destroy();\n });\n return modal;\n }, this).catch(Notification.exception);\n };\n\n /**\n * Initialize board.\n *\n * @method init\n */\n var init = function() {\n serviceCall('get_board', {id: board.id, ownerid: ownerId}, function(columns) {\n // Init\n if (columns) {\n for (var index in columns) {\n addColumn(\n columns[index].id,\n columns[index].name,\n columns[index].locked,\n columns[index].notes || {},\n options.colours[columns[index].id % options.colours.length]\n );\n }\n }\n\n if (isEditor) {\n addNewColumnButton();\n }\n\n lastHistoryId = board.historyid;\n\n if (isEditor) {\n updateSortable();\n columnSorting();\n }\n\n updateBoard();\n });\n };\n\n // Get strings\n var stringsInfo = [];\n for (var string in strings) {\n stringsInfo.push({key: string, component: 'mod_board'});\n }\n\n $.when(getStrings(stringsInfo)).done(function(results) {\n var index = 0;\n for (string in strings) {\n strings[string] = results[index++];\n }\n\n init();\n });\n}\n"],"names":["settings","strings","default_column_heading","post_button_text","cancel_button_text","remove_note_title","remove_note_text","remove_column_title","note_changed_title","note_changed_text","note_deleted_text","rate_note_title","rate_note_text","rate_remove_note_text","Ok","delete","Cancel","warning","modal_title_new","modal_title_edit","option_youtube","option_image","option_link","aria_newcolumn","aria_newpost","aria_deletecolumn","aria_movecolumn","aria_deletepost","aria_movepost","aria_editpost","aria_addmedia","aria_addmedianew","aria_deleteattachment","aria_postedit","aria_canceledit","aria_postnew","aria_cancelnew","aria_ratepost","invalid_file_extension","invalid_file_size_min","invalid_file_size_max","invalid_youtube_url","options","JSON","parse","board","contextid","reloadTimer","lastHistoryId","isEditor","usersCanEdit","userId","parseInt","userFullname","ownerId","mediaSelection","mediaselection","editingNote","isReadOnlyBoard","readonly","showauthorofnote","allowshowauthorofnoteonboard","ratingenabled","sortby","editModal","enableblanktarget","serviceCall","method","args","callback","failcallback","stopUpdating","call","methodname","done","data","fail","error","exception","_serviceCall","apply","arguments","updateBoard","getNote","ident","getNoteTextForNote","note","find","getNoteHeadingForNote","getNoteBorderForNote","getNoteAttachmentsForNote","textIdentifierForNote","noteText","html","noteHeading","noteAttachment","attachmentDataForNote","length","replace","split","slice","join","info","updateNoteAria","noteId","columnIdentifier","closest","text","noteIdentifier","deleteNoteString","attr","moveNoteString","editNoteString","updateColumnAria","columnId","column","newNoteString","moveColumnString","deleteColumnString","each","index","stopNoteEdit","noteBorder","show","hide","remove","sortAfterDelete","columnID","sortorder","getColumn","children","filter","_","element","so","setAttachment","attachment","type","attType","val","decodeText","url","attachmentInfo","attachmentUrl","attachmentFile","prop","attachmentTypeToString","FileReader","attachmentTypeChanged","previewAttachment","filename","filecontents","encodeText","fileElem","elem","removeClass","addClass","blanktarget","videoID","match","undefined","getEmbedUrl","addNote","columnid","heading","content","owner","rating","ismynote","id","iseditable","pendingNote","notecontent","notecontrols","noteAuthorusername","noteAriaText","attachmentPreview","fullname","append","columnContent","beginEdit","showModalForm","startNoteEdit","rateElement","handleAction","result","canrate","rateRemoveText","hasrated","confirm","status","historyid","sortNotes","then","rateModal","getRoot","on","ModalEvents","hidden","rateNote","removeElement","deleteNote","moveElement","init","moveNote","editElement","updateSortable","fullScreenNote","lastOne","last","insertAfter","prepend","addColumn","name","locked","notes","colour","headerStyle","nameCache","columnHeader","columnSort","columnName","columnNewContent","hideheaders","lockIcon","lockElement","lockstring","str","lockColumn","moveColumn","getColumnName","callBeforeOnKeyEditing","is","Error","e","isAriaTriggerKey","keyCode","preventDefault","editable","handleEditableAction","toggleFontSize","closeOnEnter","newNoteButton","noteicon","timecreated","userid","columnSorting","selectHeadingColour","colCount","colourCount","colours","updateNote","processBoardHistory","ownerid","since","boardhistory","item","boardid","action","formModal","historyData","alert","forEach","detach","appendTo","instant","history_refresh","setTimeout","clearTimeout","toggle","desc","asc","sortCol","parent","direction","a","b","sortElements","sort","fromColumnID","sortable","connectWith","cancel","handle","start","ui","stop","tocolumn","this","noteid","payload","updateSortOrders","movingColumnId","axis","containment","toColumnID","noteID","newSortOrder","toColumn","movedNote","oldSortOrder","toChildren","sortOrder","fromChildren","getBody","params","Fragment","loadFragment","title","create","ModalFactory","types","SAVE_CANCEL","body","large","removeOnClose","modal","getBodyPromise","saveInProgress","setLarge","setSaveButtonText","setButtonText","save","submit","changeEvent","document","createEvent","initEvent","get","reportValidity","dispatchEvent","invalid","$","merge","first","focus","formData","stringify","serialize","jsonformdata","Y","use","M","core_formchangechecker","reset_form_dirty_state","destroy","mediaSelect","ytButton","pictureButton","linkButton","updateMediaButtons","addYoutube","addImage","addLink","postButton","cancelButton","modalRoot","button","getActionSelector","updateModalAria","catch","Notification","modalBody","createElement","clone","preview","commentArea","fetchFor","CANCEL","columns","newBusy","columnicon","stringsInfo","string","push","key","component","when","results","rawText","encodedText"],"mappings":";;;;;;;uFAyJwBA,cAGhBC,QAAU,CACVC,uBAAwB,GACxBC,iBAAkB,GAClBC,mBAAoB,GACpBC,kBAAmB,GACnBC,iBAAkB,GAClBC,oBAAqB,GACrBC,mBAAoB,GACpBC,kBAAmB,GACnBC,kBAAmB,GACnBC,gBAAiB,GACjBC,eAAgB,GAChBC,sBAAuB,GACvBC,GAAI,GACJC,OAAQ,GACRC,OAAQ,GACRC,QAAS,GACTC,gBAAiB,GACjBC,iBAAkB,GAClBC,eAAgB,GAChBC,aAAc,GACdC,YAAa,GAEbC,eAAgB,GAChBC,aAAc,GACdC,kBAAmB,GACnBC,gBAAiB,GACjBC,gBAAiB,GACjBC,cAAe,GACfC,cAAe,GACfC,cAAe,GACfC,iBAAkB,GAClBC,sBAAuB,GACvBC,cAAe,GACfC,gBAAiB,GACjBC,aAAc,GACdC,eAAgB,GAChBC,cAAe,GAEfC,uBAAwB,GACxBC,sBAAuB,GACvBC,sBAAuB,GAEvBC,oBAAqB,IAIrBC,QAAUC,KAAKC,MAAM5C,SAASA,WAAa,GAC3C6C,MAAQH,QAAQG,OAAS,GACzBC,UAAYJ,QAAQI,cAUpBC,YAAc,KACdC,cAAgB,KAChBC,SAAWP,QAAQO,WAAY,EAC/BC,aAAeR,QAAQQ,aACvBC,OAASC,SAASV,QAAQS,UAAY,EACtCE,aAAeX,QAAQW,aACvBC,QAAUF,SAASV,QAAQY,SAC3BC,eAAiBb,QAAQc,gBAfG,EAgB5BC,YAAc,EACdC,gBAAkBhB,QAAQiB,WAAY,EACtCC,iBAAmBlB,QAAQkB,mBAAoB,EAC/CC,6BAA+BnB,QAAQmB,+BAAgC,EACvEC,cAAgBpB,QAAQoB,cACxBC,OAASrB,QAAQqB,QAjBD,EAkBhBC,UAAY,KACZC,kBAA6D,IAAxCb,SAASV,QAAQuB,mBAUtCC,YAAc,SAASC,OAAQC,KAAMC,SAAUC,cAChC,kBAAXH,QACAI,eArMS,SAASJ,OAAQC,KAAMC,SAAUC,4BAC7CE,KAAK,CAAC,CACPC,WAAY,aAAeN,OAC3BC,KAAMA,KACNM,KAAM,SAASC,MACXN,SAASM,OAEbC,KAAM,SAASC,6BACEC,UAAUD,OACnBP,cACAA,aAAaO,WA6LrBE,CAAaZ,OAAQC,MAAM,WACnBC,UACAA,SAASW,MAAM,KAAMC,WAEV,kBAAXd,QAAwC,aAAVA,QAC9Be,aAAY,KAEjBZ,eASHa,QAAU,SAASC,cACZ,mBAAE,2BAA6BA,MAAQ,OAU9CC,mBAAqB,SAASC,aACvB,mBAAEA,MAAMC,KAAK,yBAsBpBC,sBAAwB,SAASF,aAC1B,mBAAEA,MAAMC,KAAK,4BAUpBE,qBAAuB,SAASH,aACzB,mBAAEA,MAAMC,KAAK,2BAUpBG,0BAA4B,SAASJ,aAC9B,mBAAEA,MAAMC,KAAK,+BAUpBI,sBAAwB,SAASL,UAC7BM,SAAWP,mBAAmBC,MAAMO,OACpCC,YAAcN,sBAAsBF,MAAMO,OAC1CE,eAAiBC,sBAAsBV,aAEvCQ,YAAYG,OAAS,EACdH,YAEPF,SAASK,OAAS,EACXL,SAASM,QAAQ,eAAgB,KAAKA,QAAQ,MAAO,KAAKC,MAAM,OAAOC,MAAM,EAAG,GAAGC,KAAK,KAE/FN,eAAeO,MAAQP,eAAeO,KAAKL,OAAS,EAC7CF,eAAeO,KAEnB,MASPC,eAAiB,SAASC,YACtBlB,KAAOH,QAAQqB,QACfC,iBAAmBnB,KAAKoB,QAAQ,iBAAiBnB,KAAK,0BAA0BoB,UAEhFH,OAAQ,KACJI,eAAiBjB,sBAAsBL,MACvCuB,iBAAmB5G,QAAQ0B,gBAAgBuE,QAAQ,WAAYO,kBAAkBP,QAAQ,SAAUU,gBAEvGtB,KAAKC,KAAK,gBAAgBuB,KAAK,aAAcD,kBAAkBC,KAAK,QAASD,sBAEzEE,eAAiB9G,QAAQ2B,cAAcsE,QAAQ,SAAUU,gBAC7DtB,KAAKC,KAAK,cAAcuB,KAAK,aAAcC,gBAAgBD,KAAK,QAASC,oBAErEC,eAAiB/G,QAAQ4B,cAAcqE,QAAQ,SAAUU,gBAC7DtB,KAAKC,KAAK,cAAcuB,KAAK,aAAcE,gBAAgBF,KAAK,QAASE,gBAEzE1B,KAAKC,KAAK,qBAAqBuB,KAAK,aAAc7G,QAAQoC,cAAc6D,QAAQ,WAC5EO,kBAAkBP,QAAQ,SAAUU,iBACxCtB,KAAKC,KAAK,kBAAkBM,KAAKe,kBAWrCK,iBAAmB,SAASC,cACxBC,QAAS,mBAAE,4BAA8BD,SAAW,KACpDT,iBAAmBU,OAAO5B,KAAK,0BAA0BoB,OACzDS,cAAgBnH,QAAQuB,aAAa0E,QAAQ,WAAYO,kBACzDY,iBAAmBpH,QAAQyB,gBAAgBwE,QAAQ,WAAYO,kBAC/Da,mBAAqBrH,QAAQwB,kBAAkByE,QAAQ,WAAYO,kBACvEU,OAAO5B,KAAK,YAAYuB,KAAK,aAAcM,eAAeN,KAAK,QAASM,eACxED,OAAO5B,KAAK,oBAAoBuB,KAAK,aAAcO,kBAAkBP,KAAK,QAASO,kBACnFF,OAAO5B,KAAK,kBAAkBuB,KAAK,aAAcQ,oBAAoBR,KAAK,QAASQ,oBAEnFH,OAAO5B,KAAK,eAAegC,MAAK,SAASC,MAAOlC,MAC5CiB,gBAAe,mBAAEjB,MAAMX,KAAK,cAShC8C,aAAe,cACVhE,iBAKD6B,KAAOH,QAAQ1B,gBAEf6B,KAAM,KACFQ,YAAcN,sBAAsBF,MACpCM,SAAWP,mBAAmBC,MAC9BoC,WAAajC,qBAAqBH,MAGtCQ,YAAY6B,OACZD,WAAWC,OACX/B,SAAS+B,OACJ7B,YAAYD,SACbC,YAAY8B,OACZF,WAAWE,SAEVhC,SAASC,QAAUC,YAAYD,SAChCD,SAASgC,OACTF,WAAWE,QAInBnE,YAAc,OAzBV0B,QAAQ,GAAG0C,gBAkGbC,gBAAkB,CAACC,SAAUC,iBAC3Bb,OALWY,CAAAA,WACR,uDAA+BA,sCAIzBE,CAAUF,UACRZ,OAAOe,WAAWC,QAAO,CAACC,EAAGC,UACjCjF,UAAS,mBAAEiF,SAAS1D,KAAK,cAAgBvB,SAAS4E,aAEpDT,MAAK,CAACa,EAAGC,eACVC,IAAK,mBAAED,SAAS1D,KAAK,iCACvB0D,SAAS1D,KAAK,YAAa2D,GAAK,WAkGtCC,cAAgB,SAASjD,KAAMkD,gBAC3BzC,eAAiBL,0BAA0BJ,SAC3CS,eAAgB,CACXyC,WAGDA,WAAWC,MAAQ,GAFnBD,WAAa,CAACC,KAAM,SAIpBC,QAAU3C,eAAeR,KAAK,mBAClCmD,QAAQC,IAAIH,WAAWC,KAAOD,WAAWC,KAAO,KAC5CC,QAAQC,MAAQ,MAChB5C,eAAeR,KAAK,SAASoD,IAAIC,WAAWJ,WAAWlC,OACvDP,eAAeR,KAAK,QAAQoD,IAAIC,WAAWJ,WAAWK,OAjDtC,SAASvD,UAC7BS,eAAiBL,0BAA0BJ,MAC3CmD,KAAO1C,eAAeR,KAAK,mBAAmBoD,MAC9CG,eAAiB/C,eAAeR,KAAK,SACrCwD,cAAgBhD,eAAeR,KAAK,QACpCyD,eAAiBjD,eAAeR,KAAK,mBAErCkD,KAAO,KACPK,eAAeG,KAAK,cAAehJ,QAAQ,UAAYiJ,uBAAuBT,MAAQ,UACtFM,cAAcE,KAAK,cAAehJ,QAAQ,UAAYiJ,uBAAuBT,MAAQ,SAErFK,eAAenB,OAjXE,GAkXbc,MAA4BU,YAC5BH,eAAerB,OACfoB,cAAcnB,SAEdoB,eAAepB,OACfmB,cAAcpB,UAGlBmB,eAAelB,OACfmB,cAAcnB,OACdoB,eAAepB,OAEfkB,eAAeH,IAAI,IACnBI,cAAcJ,IAAI,KA0BlBS,CAAsB9D,MAE1B+D,kBAAkB/D,KAAMkD,aAUxBxC,sBAAwB,SAASV,UAC7BkD,WAAa,CAACC,KAAM,EAAGnC,KAAM,KAAMuC,IAAK,KAAMS,SAAU,KAAMC,aAAc,MAC5ExD,eAAiBL,0BAA0BJ,SAC3CS,eAAeE,OAAQ,CACvBuC,WAAWC,KAAO1C,eAAeR,KAAK,mBAAmBoD,MACzDH,WAAWlC,KAAOkD,WAAWzD,eAAeR,KAAK,SAASoD,OAC1DH,WAAWK,IAAMW,WAAWzD,eAAeR,KAAK,QAAQoD,WACpDc,SAAW1D,eAAeR,KAAK,yBAC/BkE,SAAS9E,KAAK,cACd6D,WAAWc,SAAWG,SAAS9E,KAAK,YACpC6D,WAAWe,aAAeE,SAAS9E,KAAK,wBAG1C6D,WAAWlC,MAASkC,WAAWlC,KAAKL,QAAauC,WAAWK,KAAQL,WAAWK,IAAI5C,QACnFuC,WAAWc,WACbd,WAAWC,KAAO,GAGfD,YAUPU,uBAAyB,SAAST,aAC1BA,UACC,UAAY,cACZ,UAAY,YACZ,UAAY,sBACD,WA2BpBY,kBAAoB,SAAS/D,KAAMkD,gBAC/BkB,KAAOpE,KAAKC,KAAK,yBAChBiD,aACDA,WAAaxC,sBAAsBV,OAGlCD,mBAAmBC,MAAMO,OAAOI,OAGjCyD,KAAKC,YAAY,oBAFjBD,KAAKE,SAAS,oBAKlBF,KAAKC,YAAY,mBACjBD,KAAKC,YAAY,iBACjBD,KAAKC,YAAY,eACbnB,WAAWc,UAhfM,GAgfMlG,SAASoF,WAAWC,MAC3CiB,KAAK7D,yBAAkB2C,WAAWe,+BAAsBf,WAAWlC,gEAEnEoD,KAAKE,SAAS,iBACdF,KAAK/B,YACF,GAAIa,WAAWK,IAAK,OACjBgB,YAAc5F,kBAAoB,mBAAqB,UACrDb,SAASoF,WAAWC,YAxfX,OA0fLI,IAzCCA,CAAAA,UAGbiB,QAAUjB,IAAIkB,MADN,gDAEPD,cAA0BE,IAAfF,QAAQ,IAA0C,KAAtBA,QAAQ,GAAG7D,wDAGN6D,QAAQ,IAF9C,MAoCWG,CAAYzB,WAAWK,KACrB,OAARA,IACAa,KAAK7D,KAAK5F,QAAQwC,sBAElBiH,KAAK7D,KAAK,gBAAkBgD,IAAlB,2OAIVa,KAAKE,SAAS,mBAAmBA,SAAS,sBAE9CF,KAAK/B,kBAngBI,EAugBT+B,KAAK7D,yBAAkB2C,WAAWK,sBAAaL,WAAWlC,wEAE1DoD,KAAKE,SAAS,iBACdF,KAAK/B,kBAzgBG,EA4gBR+B,KAAK7D,KAAK,YAAc2C,WAAWK,IAAM,sCAAwCgB,YAAc,KACrFrB,WAAWlC,MAAQkC,WAAWK,KAAO,QAC/Ca,KAAKE,SAAS,eACdF,KAAK/B,qBAGL+B,KAAK7D,KAAK,IACV6D,KAAK9B,aAGb8B,KAAK7D,KAAK,IACV6D,KAAK9B,QAiBTsC,QAAU,SAASC,SAAU/E,MAAOgF,QAASC,QAAS7B,WAAY8B,MAAOtC,UAAWuC,YAChFC,SAAWF,MAAMG,IAAMtH,SAAWiC,MAClCsF,WAAazH,UAAauH,WAAa9G,oBAEtC0B,MAAO,KACJuF,YAAcxF,QAAQ,GACtBwF,aACAA,YAAY9C,YA5iBJ,GAijBZ9D,OAAuB,EACR,uDAA+BoG,sCAAoCjC,WAC1DC,QAAO,CAACC,EAAGC,UACxBjF,UAAS,mBAAEiF,SAAS1D,KAAK,eAAiBvB,SAAS4E,aAErDT,MAAK,CAACa,EAAGC,eACVC,IAAK,mBAAED,SAAS1D,KAAK,iCACvB0D,SAAS1D,KAAK,YAAa2D,GAAK,UAItChD,MAAO,mBAAE,wCAA0C6E,SAAW,iBAAmB/E,MACjF,qBAAuB4C,UAAY,YACnCwC,UACAlF,KAAKsE,SAAS,oBAEdc,YACApF,KAAKsE,SAAS,0BAEbY,UAAaE,YACdpF,KAAKsE,SAAS,wBAGdgB,aAAc,mBAAE,8CAChBC,cAAe,mBAAE,+CACjB/E,aAAc,mBAAE,qDAAuDsE,SAAoB,IAAM,UACjGU,oBAAqB,mBAAE,IACvBpD,YAAa,mBAAE,6CACf9B,UAAW,mBAAE,kDAAoDyE,SAAoB,IAAM,UAC3FU,cAAe,mBAAE,uFACjBC,mBAAoB,mBAAE,4CAEU,GAAhCnH,8BAA4D,GAApBD,iBAA0B,KAC9DqH,SAAW,GAGXA,SAFAT,SAEWnH,aAEAiH,MAAMW,SAGrBH,mBAAqB,mEACqBG,SADrB,uDAGTA,SAHS,gBAQzBL,YAAYM,OAAOpF,aACnB8E,YAAYM,OAAOJ,oBACnBF,YAAYM,OAAOxD,YACnBkD,YAAYM,OAAOtF,UACnBgF,YAAYM,OAAOH,cAEnBH,YAAYM,OAAOF,mBACnB1F,KAAK4F,OAAON,iBAERO,eAAgB,mBAAE,4BAA8BhB,SAAW,2BAE3DiB,UAAY,MA/YA,SAAShG,UAErB3B,YAAa,IACTA,aAAe2B,aAGnBqC,kBAGArC,MAAO,KACHuF,YAAcxF,QAAQ,GACtBwF,aACAA,YAAY9C,aAIhBvC,KAAOH,QAAQC,OACfE,OACA+F,cAAc/F,MAEVF,QACA3B,YAAc2B,QA2XlBkG,CAAclG,WAGdA,MAAO,IACHtB,cAAe,CACfwB,KAAKsE,SAAS,8BACV2B,aAAc,kGAA0EhB,mBAE5FiB,aAAaD,aAAa,MAvUvB,SAASnG,UACftB,gBAGDJ,qBAIA4B,KAAOH,QAAQC,OACfmF,OAASjF,KAAKC,KAAK,qBACnBgF,OAAO5F,KAAK,cAGhB4F,OAAO5F,KAAK,YAAY,GAExBT,YAAY,gBAAiB,CAACuG,GAAIrF,QAAQ,SAASqG,WAC3CA,OAAOC,QAAS,OACVC,eAAiBF,OAAOG,SAAW3L,QAAQY,sBAAwBZ,QAAQW,qCACpEiL,QACT5L,QAAQU,gBACRgL,eACA1L,QAAQa,GACRb,QAAQe,QACR,WACIkD,YAAY,YAAa,CAACuG,GAAIrF,QAAQ,SAASqG,QACvCA,OAAOK,SACP9I,cAAgByI,OAAOM,UACvBxB,OAAO1E,gBAAS4F,OAAOlB,aA3U7B,GA4UUxG,QACAiI,UAAU1G,KAAKoB,QAAQ,2BAG/B6D,OAAO5F,KAAK,YAAY,SAGlCsH,MAAK,SAASC,WAEZA,UAAUC,UAAUC,GAAGC,sBAAYC,QAAQ,WACvC/B,OAAO5F,KAAK,YAAY,eAkS5B4H,CAASnH,UAEbyF,aAAaK,OAAOK,gBAGpBb,WAAY,KACR8B,eAAgB,mBAAE,8EACtBhB,aAAagB,eAAe,MAhYvB,SAASpH,6BACTyG,QACT5L,QAAQI,kBACRJ,QAAQK,iBACRL,QAAQc,OACRd,QAAQe,QACR,WACIkD,YAAY,cAAe,CAAEuG,GAAIrF,QAAS,SAAUqG,WAC5CA,OAAOK,OAAQ,CACf9I,cAAgByI,OAAOM,cACnBzG,KAAOH,QAAQC,UAxQnB,GAyQIrB,OAAuB,KACnBgE,SAAWzC,KAAKX,KAAK,UACrBqD,UAAY1C,KAAKX,KAAK,aAC1BmD,gBAAgBC,SAAUC,WAE9B1C,KAAKuC,gBAiXT4E,CAAWrH,UAGfyF,aAAaK,OAAOsB,eAEA,GAAhBtJ,cAAqBD,SAAU,KAC3ByJ,aAAc,mBAAE,wFACpB7B,aAAaK,OAAOwB,sCACJC,KAAKrJ,QAASsJ,cAG9BC,aAAc,mBAAE,wFACpBhC,aAAaK,OAAO2B,aACpBrB,aAAaqB,aAAa,KACtBzB,eAEJ0B,iBACAvE,cAAcjD,KAAMkD,iBAEpBa,kBAAkB/D,KAAMkD,YAG5BlD,KAAK4F,OAAOL,cAEZW,aAAaZ,aAAa,IAAMmC,eAAe3H,MAAOwF,eAEjD9E,YAAYD,SACbC,YAAY8B,OACZF,WAAWE,SAEVhC,SAASC,QAAUC,YAAYD,SAChCD,SAASgC,OACTF,WAAWE,YAGXoF,QAAU7B,cAAc5F,KAAK,eAAe0H,OAE5CD,QAAQ/G,OACRX,KAAK4H,YAAYF,SAEjB7B,cAAcgC,QAAQ7H,8BAGxB,4BAA8B6E,SAAW,8BAA8Be,OAAO5F,MAEhFA,KAAKsC,OACLwD,aAcJgC,UAAY,SAAShI,MAAOiI,KAAMC,OAAQC,MAAOC,YAC7CC,qDAAgDD,gBAChD9C,WAAazH,SACbyK,UAAY,KACZvG,QAAS,yFAAiEmG,oCACnEG,oCAA2BrI,mBAClCuI,cAAe,mBAAE,2CACjBC,YAAa,mBAAE,gDACfC,YAAa,mBAAE,iFAAmFR,KAAO,UACzGlC,eAAgB,mBAAE,4CAClB2C,kBAAmB,mBAAE,kDArsBT,GAusBZ/J,QACA4J,aAAazC,OAAO0C,YAExBD,aAAazC,OAAO2C,YAEhBnL,QAAQqL,aACRF,WAAWjE,SAAS,UAGxBgE,WAAWxB,GAAG,SAAS,WACnBJ,UAAUb,eAAe,MAGzBT,WAAY,CACZvD,OAAOyC,SAAS,kCACVoE,SAAWV,OAAS,UAAY,YAChCW,aAAc,iDAAyBD,6DACvCE,WAAaZ,OAAS,qBAAuB,2CACzCY,WAAY,YAAab,MAAM3I,MAAK,SAASyJ,KACnDF,YAAYnH,KAAK,aAAcqH,KAC/BF,YAAYnH,KAAK,QAASqH,QAG9B3C,aAAayC,aAAa,WAChBG,WAA4C,SAA/BjH,OAAOL,KAAK,eAC/B5C,YAAY,cAAe,CAACuG,GAAIrF,MAAO0G,OAAQsC,aAAa,SAAS3C,cAC3DoC,WAAa1G,OAAO5B,KAAK,0BAA0BoB,OACrD8E,OAAOK,SACHsC,YACAH,YAAYtE,YAAY,aAAaC,SAAS,WAC9CzC,OAAOL,KAAK,cAAe,QAC3BK,OAAO5B,KAAK,yBAAyBqE,SAAS,8BACpC,qBAAsB,YAAaiE,YAAYnJ,MAAK,SAASyJ,KACnEF,YAAYnH,KAAK,aAAcqH,KAC/BF,YAAYnH,KAAK,QAASqH,UAG9BF,YAAYtE,YAAY,WAAWC,SAAS,aAC5CzC,OAAOL,KAAK,cAAe,SAC3BK,OAAO5B,KAAK,yBAAyBoE,YAAY,8BACvC,uBAAwB,YAAakE,YAAYnJ,MAAK,SAASyJ,KACrEF,YAAYnH,KAAK,aAAcqH,KAC/BF,YAAYnH,KAAK,QAASqH,SAGlCnL,cAAgByI,OAAOM,UACvBe,wBAIZa,aAAazC,OAAO+C,aAEpBN,aAAa/D,SAAS,qBAChB8C,aAAc,mBAAE,oFACtBiB,aAAazC,OAAOwB,wCACFC,KAAK0B,gBACnB7B,eAAgB,mBAAE,kFACtBhB,aAAagB,eAAe,2BACXX,QACT5L,QAAQM,qBACR,mBAAU,qBAAsB,YAAa+N,cAAclJ,QAC3DnF,QAAQc,OACRd,QAAQe,QACR,WACIkD,YAAY,gBAAiB,CAACuG,GAAIrF,QAAQ,SAASqG,QAC3CA,OAAOK,SACP3E,OAAOU,SACP7E,cAAgByI,OAAOM,oBAO3C4B,aAAazC,OAAOsB,kBAGxBrF,OAAO+D,OAAOyC,cACdxG,OAAO+D,OAAOC,eACdhE,OAAO+D,OAAO4C,kBAEVpD,cAn3BiB,SAAShB,KAAMrF,SAAUkK,2BAC9C7E,KAAK8E,GAAG,mBACF,IAAIC,MAAM,gFAIb/E,KAAK0C,GAAG,qBAAqB,SAASsC,MAC3B,YAAVA,EAAEjG,KAAoB,KAClBkG,iBAAiBD,EAAEE,UAAalF,KAAK8E,GAAG,sBACxCE,EAAEG,iBACEN,wBACAlK,WAEJqF,KAAKoF,SAAS,QACVP,8BAQZlK,cA81BI0K,CAAqBlB,YAAY,WAC7BH,UAAYG,WAAWhI,UACxB,GAEHgI,WAAWiB,SAAS,CAChBE,gBAAgB,EAChBC,cAAc,EACd5K,SAAU,SAASM,MACXA,KAAK0F,QACLnG,YAAY,gBAAiB,CAACuG,GAAIrF,MAAOiI,KAAMQ,WAAWhI,SAAS,SAAS4F,QACnEA,OAAOK,QAIR9I,cAAgByI,OAAOM,UACvB9E,iBAAiB7B,SAJjByI,WAAWhI,KAAK6H,WAChBA,UAAY,SAKjB,WACCG,WAAWhI,KAAK6H,WAChBA,UAAY,SAGhBG,WAAWhI,KAAK6H,WAChBA,UAAY,WAMvBhK,gBAAiB,OACZwL,eAAgB,mBAAE,4GACyBxM,QAAQyM,SAAW,yBACpErB,iBAAiB5C,OAAOgE,eACW,SAA/B/H,OAAOL,KAAK,gBACZoI,cAActF,SAAS,UAE3B4B,aAAasC,iBAAiBvI,KAAK,aAAa,WAE5C2E,QAAQ9E,MAAO,EAAG,KAAM,KAAM,KAAM,CAACqF,GAAItH,QAAS,EAAG,UAIzD6J,SAAU,mBAAE,oCAAoCC,UAChDD,QAAQ/G,OACRkB,OAAO+F,YAAYF,6BAEjB,cAAc9B,OAAO/D,QAGvBoG,UACK,IAAI/F,SAAS+F,MAAO,KACjBvF,UAAsB,GAAVjE,OAAcwJ,MAAM/F,OAAOQ,UAAYuF,MAAM/F,OAAO4H,YAEpElF,QAAQ9E,MAAOmI,MAAM/F,OAAOiD,GAAI8C,MAAM/F,OAAO4C,QAASmD,MAAM/F,OAAO6C,QAC/D,CAAC5B,KAAM8E,MAAM/F,OAAOiB,KAAMnC,KAAMiH,MAAM/F,OAAOlB,KAAMuC,IAAK0E,MAAM/F,OAAOqB,KACrE,CAAC4B,GAAI8C,MAAM/F,OAAO6H,OAASpE,SAAUsC,MAAM/F,OAAOyD,UAClDjD,UAAWuF,MAAM/F,OAAO+C,QAGpCyB,UAAUb,eACVlE,iBAAiB7B,QACbnC,UAA4B,GAAhBC,eACZ4J,iBAEA7J,UACAqM,uBASFhB,cAAiB7D,KACZ,uDAA+BA,UAAQlF,KAAK,0BAA0BM,aAuC3E0J,oBAAsB,SACpBC,UAAW,mBAAE,iBAAiBvJ,OAAS,EACvCwJ,YAAc/M,QAAQgN,QAAQzJ,cAC3BvD,QAAQgN,QAAQF,SAAWC,kBAWlCE,WAAa,SAASrK,KAAM8E,QAASzF,UACjCmB,YAAcN,sBAAsBF,MACpCM,SAAWP,mBAAmBC,MAC9BoC,WAAajC,qBAAqBH,MAEtCM,SAASC,KAAKlB,KAAK0F,SACnBvE,YAAYD,KAAKlB,KAAKyF,SACtB7B,cAAcjD,KAAMX,KAAK6D,YACzBjC,eAAe5B,KAAK8F,IAGpB3E,YAAY6B,OACZD,WAAWC,OACX/B,SAAS+B,OACJ7B,YAAYD,SACbC,YAAY8B,OACZF,WAAWE,SAEVhC,SAASC,QAAUC,YAAYD,SAChCD,SAASgC,OACTF,WAAWE,SASfgI,oBAAsB,WACtB1L,YAAY,gBAAiB,CAACuG,GAAI5H,MAAM4H,GAAIoF,QAASvM,QAASwM,MAAO9M,gBAAgB,SAAS+M,kBACrF,IAAIvI,SAASuI,aAAc,KACxBC,KAAOD,aAAavI,UACpBwI,KAAKC,SAAWpN,MAAM4H,QAItB9F,KAAOhC,KAAKC,MAAMoN,KAAK3F,YACR,YAAf2F,KAAKE,OAAsB,KACvBlI,UAAsB,GAAVjE,OAAcY,KAAKqD,UAAYrD,KAAKyK,YACpDlF,QAAQvF,KAAKwF,SAAUxF,KAAK8F,GAAI9F,KAAKyF,QAASzF,KAAK0F,QAAS1F,KAAK6D,WAC7D,CAACiC,GAAIuF,KAAKX,QAASrH,UAAWrD,KAAK4F,QACvChE,eAAe5B,KAAK8F,IACpBuB,WAAU,mBAAE,4BAA8BrH,KAAKwF,SAAW,iCACvD,GAAmB,eAAf6F,KAAKE,OAAyB,KACjC5K,KAAOH,QAAQR,KAAK8F,IACpB0F,UAAYnM,UACZoM,YAAczL,QACdW,KAAM,CACYE,sBAAsBF,MAEpC7B,aAAekB,KAAK8F,yBACPoB,QACT5L,QAAQO,mBACRP,QAAQQ,kBACRR,QAAQa,GACRb,QAAQe,QACR,WACImP,UAAUvI,OACV+H,WAAWrK,KAAMQ,EAAasK,aAC9B3I,kBAIRkI,WAAWrK,KAAMQ,EAAanB,YAGnC,GAAmB,eAAfqL,KAAKE,OAAyB,CACjCzM,aAAekB,KAAK8F,2BACP4F,MAAMpQ,QAAQgB,QAAShB,QAAQS,mBAC5C+G,oBAEAnC,KAAOH,QAAQR,KAAK8F,OAj+BpB,GAk+BA1G,OAAuB,KACnBgE,SAAWzC,KAAKX,KAAK,UACrBqD,UAAY1C,KAAKX,KAAK,aAC1BmD,gBAAgBC,SAAUC,WAE9B1C,KAAKuC,cAEF,GAAmB,cAAfmI,KAAKE,OACZ9C,UAAUzI,KAAK8F,GAAI9F,KAAK0I,MAAM,EAAO,GAAIkC,4BACtC,GAAmB,eAAfS,KAAKE,OAAyB,OAC/BrN,OAAQ,mBAAE,cAChB8B,KAAKqD,UAAUsI,SAAQnJ,SACGtE,MAAM0C,yCAAkC4B,cAChDoJ,SAASC,SAAS3N,eAEjC,GAAmB,iBAAfmN,KAAKE,2BACV,6BAA+BvL,KAAK8F,GAAK,6BAA6B5E,KAAKlB,KAAK0I,MAClFpG,iBAAiBtC,KAAK8F,SACnB,GAAmB,eAAfuF,KAAKE,2BACV,6BAA+BvL,KAAK8F,GAAK,MAAM3D,KAAK,cAAenC,KAAK2I,QACtE3I,KAAK2I,2BACH,6BAA+B3I,KAAK8F,GAAK,MAAMlF,KAAK,yBAAyBqE,SAAS,8BAEtF,6BAA+BjF,KAAK8F,GAAK,MAAMlF,KAAK,yBAAyBoE,YAAY,UAE/FmD,sBACG,GAAmB,iBAAfkD,KAAKE,OAA2B,KACnC/I,QAAS,mBAAE,6BAA+BxC,KAAK8F,GAAK,MACpDhH,aAAe0D,OAAO5B,KAAK,2BAA6B9B,YAAc,MAAMwC,QAC5EwB,eAEJN,OAAOU,cACJ,GAAmB,aAAfmI,KAAKE,OAAuB,KAC/B5K,KAAOH,QAAQR,KAAK8F,IACxBnF,KAAKC,KAAK,qBAAqBM,KAAKlB,KAAK4F,QArgCnC,GAsgCFxG,QACAiI,UAAU1G,KAAKoB,QAAQ,0BAG/B1D,cAAgBgN,KAAKvF,IAGzBvF,kBAUJA,YAAc,SAASuL,SACnBA,QACAb,sBACOlN,QAAQgO,gBAAkB,IAC7B3N,aACAwB,eAEJxB,YAAc4N,WAAWf,oBAA+C,IAA1BlN,QAAQgO,mBAS1DnM,aAAe,WACfqM,aAAa7N,aACbA,YAAc,MAUdiJ,UAAY,SAAS3B,QAASwG,YAuB1BC,KACAC,IAvBAC,SAAU,mBAAE3G,SAAS4G,SAAS1L,KAAK,0BACnC2L,WAAY,mBAAE7G,SAAS1F,KAAK,WAC3BuM,YAEGA,UAxjCU,GAujCVnN,OACY,OAEA,OAGhB8M,SACAK,UAAyB,OAAbA,UAAqB,OAAS,OAG7B,OAAbA,WACAF,QAAQrH,YAAY,iBACpBqH,QAAQpH,SAAS,iBAEjBoH,QAAQrH,YAAY,eACpBqH,QAAQpH,SAAS,sCAEnBS,SAAS1F,KAAK,OAAQuM,WAzkCR,GA6kCZnN,OACA+M,KAAO,SAASK,EAAGC,UACR,mBAAEA,GAAGzM,KAAK,cAAe,mBAAEwM,GAAGxM,KAAK,cAE9CoM,IAAM,SAASI,EAAGC,UACP,mBAAED,GAAGxM,KAAK,cAAe,mBAAEyM,GAAGzM,KAAK,mBAE3C,GAnlCW,GAmlCPZ,OACP+M,KAAO,SAASK,EAAGC,UACR,mBAAEA,GAAG7L,KAAK,qBAAqBoB,QAAS,mBAAEwK,GAAG5L,KAAK,qBAAqBoB,SAC9E,mBAAEyK,GAAGzM,KAAK,cAAe,mBAAEwM,GAAGxM,KAAK,cAEvCoM,IAAM,SAASI,EAAGC,UACP,mBAAED,GAAG5L,KAAK,qBAAqBoB,QAAS,mBAAEyK,GAAG7L,KAAK,qBAAqBoB,SAC9E,mBAAEwK,GAAGxM,KAAK,cAAe,mBAAEyM,GAAGzM,KAAK,mBAEpC,GA3lCS,GA2lCLZ,OAAuB,KAC1BsN,aAAe,CAACF,EAAGC,KACZ,mBAAED,GAAGxM,KAAK,cAAe,mBAAEyM,GAAGzM,KAAK,4CAE5C,iBAAiB,mBAAE0F,UAAUiH,KAAKD,cAAcb,UAAS,mBAAEnG,8BAI/D,iBAAiB,mBAAEA,UAAUiH,KAAmB,QAAdJ,UAAsBH,IAAMD,MAAMN,UAAS,mBAAEnG,WASjFyC,eAAiB,eACbyE,iCACF,4DAA4DC,SAAS,CACnEC,YAAa,2DACbC,OAAQ,oBACRC,OAAQ,aACRC,MAAO,SAASxJ,EAAGyJ,IACfN,cAAe,mBAAEM,GAAG7B,MAAMtJ,QAAQ,iBAAiB/B,KAAK,UAE5DmN,KAAM,SAAS1J,EAAGyJ,QACVvM,MAAO,mBAAEuM,GAAG7B,MACZ+B,SAAWzM,KAAKoB,QAAQ,iBACxBgD,MAAO,mBAAEsI,MACTC,OAAS3M,KAAKX,KAAK,SACnBwF,SAAW4H,SAASpN,KAAK,aAEzBqD,UADiB+J,SAASxM,KAAK,yBAAyB2C,WAC7BV,OAAM,oDAA4ByK,cAOjErF,SAAS2E,aANK,CACV9G,GAAIwH,OACJ9H,SAAUA,SACV0F,QAASvM,QACT0E,UAAWA,WAEiB0B,gBAYtCkD,SAAW,CAAC2E,aAAcW,QAASxI,QACrCyI,iBAAiBZ,aAAcW,QAAQ/H,SAAU+H,QAAQzH,GAAIyH,QAAQlK,WAErE9D,YAAY,YAAagO,SAAUzG,SAC3BA,OAAOK,QACP9I,cAAgByI,OAAOM,UACvBxF,eAAe2L,QAAQzH,IACvBvF,cACA8G,WAAU,sDAA8BkG,QAAQ/H,uCAE5CT,MACAA,KAAK8H,SAAS,cASxBlC,cAAgB,SACd8C,mCACF,cAAcZ,SAAS,CACrBC,YAAa,aACbY,KAAM,IACNC,YAAa,qBACbZ,OAAQ,oBACRC,OAAQ,mBACRC,MAAO,SAASxJ,EAAGyJ,IACfO,gBAAiB,mBAAEP,GAAG7B,MAAMtJ,QAAQ,iBAAiB/B,KAAK,UAE9DmN,KAAM,SAAS1J,EAAGyJ,QACV1K,QAAS,mBAAE0K,GAAG7B,MAEdhI,WADU,mBAAE,cAAczC,KAAK,iBACXiC,MAAML,QAK9BkH,WAJc,CACV5D,GAAI2H,eACJpK,UAAWA,gBAYrBqG,WAAc6D,UAChBhO,YAAY,cAAegO,SAAS,IAYlCC,iBAAmB,CAACZ,aAAcgB,WAAYC,OAAQC,oBACpDC,UAAW,sDAA8BH,uCACzCI,WAAY,oDAA4BH,aACxCI,aAAeD,UAAUhO,KAAK,aAG9BkO,WAAaH,SAASxK,cACtBqJ,cAAgBgB,WAChBM,WAAWtL,MAAK,CAACa,EAAG9C,YACZwN,WAAY,mBAAExN,MAAMX,KAAK,aACzBiO,aAAeH,aACXK,WAAaL,cAAgBK,WAAaF,kCACxCtN,MAAMX,KAAK,YAAamO,UAAY,GAEnCF,aAAeH,cAClBK,WAAaL,cAAgBK,WAAaF,kCACxCtN,MAAMX,KAAK,YAAamO,UAAY,UAI/C,KAECC,cADa,sDAA8BxB,yCACjBrJ,WAC9B2K,WAAWtL,MAAK,CAACa,EAAG9C,YACZwN,WAAY,mBAAExN,MAAMX,KAAK,aACzBmO,WAAaL,kCACXnN,MAAMX,KAAK,YAAamO,UAAY,MAG9CC,aAAaxL,MAAK,CAACa,EAAG9C,YACdwN,WAAY,mBAAExN,MAAMX,KAAK,aACzBmO,UAAYF,kCACVtN,MAAMX,KAAK,YAAamO,UAAY,MAIlDH,UAAUhO,KAAK,YAAa8N,mBAW5BO,QAAU,SAASf,OAAQ9H,SAAU7G,aAEjC2P,OAAS,CAAChB,OAAQA,OAAQ9H,SAAUA,SAAU0F,QAASvM,gBACpD4P,kBAASC,aAAa,YAAa,YAAarQ,UAAWmQ,SAgElE5H,cAAgB,SAAS/F,UAKrB8N,MAJA5M,OAAS,EACTU,SAAW5B,KAAKX,KAAK,UAErB8B,kBADS,mBAAE,4BAA8BS,SAAW,KAC1B3B,KAAK,0BAA0BoB,OAGzDrB,KAAKX,KAAK,UACV6B,OAASlB,KAAKX,KAAK,SACnByO,MAAQnT,QAAQkB,iBAAiB+E,QAAQ,WAAYO,mBAErD2M,MAAQnT,QAAQiB,gBAAgBgF,QAAQ,WAAYO,yCAG3C4M,OAAO,CAChB5K,KAAM6K,uBAAaC,MAAMC,YACzBJ,MAAOA,MACPK,KAAMT,QAAQxM,OAAQU,SAAU5D,SAChCoQ,OAAO,EACPC,eAAe,IAChB1H,MAAK,SAAS2H,cAEbA,MAAMC,iBAAiB5H,MAAK,eACpB6H,gBAAiB,EACrB9P,UAAY4P,MACZA,MAAMG,WACNH,MAAMI,kBAAkB/T,QAAQE,kBAChCyT,MAAMK,cAAc,SAAUhU,QAAQG,oBAEtCwT,MAAMzH,UAAUC,GAAGC,sBAAYC,QAAQ,WACnC7E,eACKnC,KAAKX,KAAK,UACXW,KAAKuC,YAIb+L,MAAMzH,UAAUC,GAAGC,sBAAY6H,MAAM,SAAUxF,GAC3CA,EAAEG,iBACF+E,MAAMzH,UAAU5G,KAAK,QAAQ4O,gBAG7BC,YAAcC,SAASC,YAAY,iBACvCF,YAAYG,UAAU,UAAU,GAAM,GAEtCX,MAAMzH,UAAUC,GAAG,SAAU,QAAQ,SAAUsC,MAC3CA,EAAEG,iBAGEiF,yBAGJA,gBAAiB,EAGLF,MAAMzH,UAAU5G,KAAK,QAAQiP,IAAI,GAAGC,kBAUhDb,MAAMzH,UAAU5G,KAAK,UAAUgC,MAAK,SAAUC,MAAOa,SACjDA,QAAQqM,cAAcN,oBAItBO,QAAUC,gBAAEC,MACZjB,MAAMzH,UAAU5G,KAAK,yBACrBqO,MAAMzH,UAAU5G,KAAK,UACrBqO,MAAMzH,UAAU5G,KAAK,gBAIrBoP,QAAQ1O,cACR0O,QAAQG,QAAQC,aAChBjB,gBAAiB,OAIjBkB,SAAWrS,KAAKsS,UAAUrB,MAAMzH,UAAU5G,KAAK,QAAQ2P,aAC3DhR,YAAY,cAAe,CAACpB,UAAWA,UAAWqS,aAAcH,WAAW,SAAUvJ,QAC7EA,OAAOK,QACc,UAAjBL,OAAOyE,QAEPlN,cAAgByI,OAAOM,UACvBzG,KAAKuC,SACLqC,QAAQhD,SAAUuE,OAAOnG,KAAKmF,GAAIgB,OAAOnG,KAAK8E,QAASqB,OAAOnG,KAAK+E,QAC/D,CAAC5B,KAAMgD,OAAOnG,KAAKmD,KAAMnC,KAAMmF,OAAOnG,KAAKgB,KAAMuC,IAAK4C,OAAOnG,KAAKuD,KAClE,CAAC4B,GAAIgB,OAAOnG,KAAK+J,QAAS5D,OAAOnG,KAAK8J,YAAa3D,OAAOnG,KAAKiF,QACnEyB,WAAU,mBAAE,4BAA8B9E,SAAW,4BACrDX,eAAekF,OAAOnG,KAAKmF,MAG3BzH,cAAgByI,OAAOM,UACvB1G,mBAAmBC,MAAMO,KAAK4F,OAAOnG,KAAK+E,SAC1C7E,sBAAsBF,MAAMO,KAAK4F,OAAOnG,KAAK8E,SAC7C7D,eAAekF,OAAOnG,KAAKmF,IAC3BlC,cAAcjD,KAAM,CAChBmD,KAAMgD,OAAOnG,KAAKmD,KAClBnC,KAAMmF,OAAOnG,KAAKgB,KAAMuC,IAAK4C,OAAOnG,KAAKuD,OAGjDpB,eAGA2N,EAAEC,IAAI,iCAAiC,WACnCC,EAAEC,uBAAuBC,4BAG7B5B,MAAM6B,WAEN7B,MAAM6B,kBA1DV3B,gBAAiB,KA73CL,GA67ChBvQ,eAA2C,CAE3CqQ,MAAMzH,UAAU5G,KAAK,uBAAuBqC,WAExC8N,YAAc9B,MAAMzH,UAAU5G,KAAK,8BACnCoQ,SAAW/B,MAAMzH,UAAU5G,KAAK,+CAChCqQ,cAAgBhC,MAAMzH,UAAU5G,KAAK,6CACrCsQ,WAAajC,MAAMzH,UAAU5G,KAAK,4CAClCuQ,mBAAqB,kBACjBH,SAAShM,YAAY,YACrBiM,cAAcjM,YAAY,YAC1BkM,WAAWlM,YAAY,YACf+L,YAAY/M,WACV,IACFgN,SAAS/L,SAAS,sBAEhB,IACFgM,cAAchM,SAAS,sBAErB,IACFiM,WAAWjM,SAAS,cAKpCkM,qBACAtK,aAAamK,UAAU,WACO,MAAtBD,YAAY/M,MACZ+M,YAAY/M,IAAI,GAEhB+M,YAAY/M,IAAI,GAEpBmN,qBACAJ,YAAY,GAAGhB,cAAcN,gBAEjC5I,aAAaoK,eAAe,WACE,MAAtBF,YAAY/M,MACZ+M,YAAY/M,IAAI,GAEhB+M,YAAY/M,IAAI,GAEpBmN,qBACAJ,YAAY,GAAGhB,cAAcN,gBAEjC5I,aAAaqK,YAAY,WACK,MAAtBH,YAAY/M,MACZ+M,YAAY/M,IAAI,GAEhB+M,YAAY/M,IAAI,GAEpBmN,qBACAJ,YAAY,GAAGhB,cAAcN,qBAGjCR,MAAMzH,UAAU5G,KAAK,0BAA0BqC,cArOzC,SAAStC,KAAMsO,WAE7BmC,WACAC,SACAC,QACAC,WACAC,aALA1P,iBAAmBnB,KAAKoB,QAAQ,iBAAiBnB,KAAK,0BAA0BoB,OAMhFyP,UAAYxC,MAAMzH,aAElB7G,KAAKX,KAAK,SAAU,KAEhBiC,eAAiBjB,sBAAsBL,MAE3C4Q,WAAajW,QAAQgC,cAAciE,QAAQ,WAAYO,kBAAkBP,QAAQ,SAAUU,gBAC3FuP,aAAelW,QAAQiC,gBAAgBgE,QAAQ,WAAYO,kBAAkBP,QAAQ,SAAUU,gBAC/FmP,WAAa9V,QAAQ6B,cAAcoE,QAAQ,SAAUjG,QAAQmB,gBAAgB8E,QAAQ,WACjFO,kBAAkBP,QAAQ,SAAUU,gBACxCoP,SAAW/V,QAAQ6B,cAAcoE,QAAQ,SAAUjG,QAAQoB,cAAc6E,QAAQ,WAC7EO,kBAAkBP,QAAQ,SAAUU,gBACxCqP,QAAUhW,QAAQ6B,cAAcoE,QAAQ,SAAUjG,QAAQqB,aAAa4E,QAAQ,WAC3EO,kBAAkBP,QAAQ,SAAUU,qBAGxCsP,WAAajW,QAAQkC,aAAa+D,QAAQ,WAAYO,kBACtD0P,aAAelW,QAAQmC,eAAe8D,QAAQ,WAAYO,kBAC1DsP,WAAa9V,QAAQ8B,iBAAiBmE,QAAQ,SAAUjG,QAAQmB,gBAAgB8E,QAAQ,WACpFO,kBACJuP,SAAW/V,QAAQ8B,iBAAiBmE,QAAQ,SAAUjG,QAAQoB,cAAc6E,QAAQ,WAAYO,kBAChGwP,QAAUhW,QAAQ8B,iBAAiBmE,QAAQ,SAAUjG,QAAQqB,aAAa4E,QAAQ,WAAYO,kBA1yCtE,GA6yCxBlD,iBACA6S,UAAU7Q,KAAK,+CAA+CuB,KAAK,aAAciP,YACjFK,UAAU7Q,KAAK,+CAA+CuB,KAAK,QAASiP,YAC5EK,UAAU7Q,KAAK,6CAA6CuB,KAAK,aAAckP,UAC/EI,UAAU7Q,KAAK,6CAA6CuB,KAAK,QAASkP,UAC1EI,UAAU7Q,KAAK,4CAA4CuB,KAAK,aAAcmP,SAC9EG,UAAU7Q,KAAK,4CAA4CuB,KAAK,QAASmP,cAGzEI,OAASD,UAAU7Q,KAAKqO,MAAM0C,kBAAkB,SAChDD,QACAA,OAAOvP,KAAK,aAAcoP,YAE9BG,OAASD,UAAU7Q,KAAKqO,MAAM0C,kBAAkB,WAC5CD,QACAA,OAAOvP,KAAK,aAAcqP,cA0LtBI,CAAgBjR,KAAMsO,OACtBA,MAAMjM,OAECiM,SACR4C,MAAMC,sBAAa3R,WACf8O,SACR4C,MAAMC,sBAAa3R,YAQtBiI,eAAiB,CAAC3H,MAAOwF,qBACnBR,QAAU5E,sBAAsBoF,aAAa/E,OAC7C6Q,WAAY,mBAAErC,SAASsC,cAAc,QAC3CD,UAAU9M,SAAS,gCACbjD,KAAOtB,mBAAmBuF,aAC5BjE,MACA+P,UAAUxL,OAAOvE,KAAKiQ,eAEpBC,SAj8CmBvR,KAi8CasF,aAh8C/B,mBAAEtF,MAAMC,KAAK,uBADKD,IAAAA,KAk8CrBuR,SACAH,UAAUxL,OAAO2L,QAAQD,eAIvBE,aAAc,mBAAEzC,SAASsC,cAAc,QAC7CG,YAAYhQ,KAAK,cAAe,gBAChC4P,UAAUxL,OAAO4L,+BACRC,SAAS3R,MAAO0R,oCAEZzD,OAAO,CAChB5K,KAAM6K,uBAAaC,MAAMyD,OACzB5D,MAAOhJ,QACPqJ,KAAMiD,YACPzK,MAAK,SAAS2H,cACbA,MAAMG,WACNH,MAAMjM,OAENiM,MAAMzH,UAAUC,GAAGC,sBAAYC,QAAQ,WAEnCsH,MAAM6B,aAEH7B,QACR5B,MAAMwE,MAAMC,sBAAa3R,YAQ5B6H,KAAO,WACPzI,YAAY,YAAa,CAACuG,GAAI5H,MAAM4H,GAAIoF,QAASvM,UAAU,SAAS2T,YAE5DA,YACK,IAAIzP,SAASyP,QACd7J,UACI6J,QAAQzP,OAAOiD,GACfwM,QAAQzP,OAAO6F,KACf4J,QAAQzP,OAAO8F,OACf2J,QAAQzP,OAAO+F,OAAS,GACxB7K,QAAQgN,QAAQuH,QAAQzP,OAAOiD,GAAK/H,QAAQgN,QAAQzJ,SApsB/C,IACjBkB,OACA+P,QAusBIjU,WAxsBJkE,QAAS,mBAAE,0CACX+P,SAAU,EACd/P,OAAO+D,OAAO,8EACVjL,QAAQsB,eAAiB,YAActB,QAAQsB,eAAiB,iDAC9DmB,QAAQyU,WAAa,yBAE3B3L,aAAarE,OAAO5B,KAAK,eAAe,WAChC2R,UAGJA,SAAU,EAEVhT,YAAY,aAAc,CAAC+L,QAASpN,MAAM4H,GAAI4C,KAAMpN,QAAQC,yBAAyB,SAASuL,QAC1F2B,UAAU3B,OAAOhB,GAAIxK,QAAQC,wBAAwB,EAAO,GAAIqP,uBAChEvM,cAAgByI,OAAOM,UACvBmL,SAAU,KACX,WACCA,SAAU,6BAIhB,cAAchM,OAAO/D,SAurBnBnE,cAAgBH,MAAMkJ,UAElB9I,WACA6J,iBACAwC,iBAGJpK,kBAKJkS,YAAc,OACb,IAAIC,UAAUpX,QACfmX,YAAYE,KAAK,CAACC,IAAKF,OAAQG,UAAW,8BAG5CC,MAAK,oBAAWL,cAAc1S,MAAK,SAASgT,aACtClQ,MAAQ,MACP6P,UAAUpX,QACXA,QAAQoX,QAAUK,QAAQlQ,SAG9BmF,2cAjuDFgC,iBAAmB,SAAS4I,YAChB,IAAPA,KAAoB,IAAPA,KASlB/N,WAAa,SAASmO,gBACjB,mBAAE,WAAWhR,KAAKgR,SAAS9R,QAShC+C,WAAa,SAASgP,oBACjB,mBAAE,WAAW/R,KAAK+R,aAAajR,QAUpC6E,aAAe,SAAS9B,KAAMrF,iBACzBqF,KAAK0C,GAAG,kBAAkB,SAASsC,MACxB,YAAVA,EAAEjG,KAAoB,KAClBkG,iBAAiBD,EAAEE,gBACnBF,EAAEG,iBAMVxK,WACAqK,EAAEG"} \ No newline at end of file +{"version":3,"file":"board.min.js","sources":["../src/board.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * A javascript module to handle the board.\n *\n * @author Karen Holland \n * @copyrigt 2021 Brickfield Education Labs \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from \"jquery\";\nimport {get_strings as getStrings, get_string as getString} from \"core/str\";\nimport Ajax from \"core/ajax\";\nimport ModalFactory from \"core/modal_factory\";\nimport ModalEvents from \"core/modal_events\";\nimport Notification from \"core/notification\";\nimport \"mod_board/jquery.editable.amd\";\nimport \"mod_board/jquery.sortable.amd\";\nimport Fragment from \"core/fragment\";\nimport Comments from \"mod_board/comments\";\nimport moveNotesDialog from \"./movenotesdialog\";\nimport moveColumnsDialog from \"./movecolumnsdialog\";\n\n/**\n * Execute a ajax call to a mod_board ajax service.\n *\n * @param {string} method\n * @param {array} args\n * @param {method} callback\n * @param {method} failcallback\n * @private\n */\nconst _serviceCall = function(method, args, callback, failcallback) {\n Ajax.call([{\n methodname: 'mod_board_' + method,\n args: args,\n done: function(data) {\n callback(data);\n },\n fail: function(error) {\n Notification.exception(error);\n if (failcallback) {\n failcallback(error);\n }\n }\n }]);\n};\n\n/**\n * Indicates if this is a keycode we want to listend to for\n * aria purposes.\n *\n * @returns {boolean}\n * @param {number} key\n */\nconst isAriaTriggerKey = function(key) {\n return key == 13 || key == 32;\n};\n\n/**\n * Encodes text into html entities.\n *\n * @param {string} rawText\n * @returns {*|jQuery}\n */\nconst encodeText = function(rawText) {\n return $('
').text(rawText).html();\n};\n\n/**\n * Decodes text from html entities.\n *\n * @param {string} encodedText\n * @returns {*|jQuery}\n */\nconst decodeText = function(encodedText) {\n return $('
').html(encodedText).text();\n};\n\n/**\n * Handler for keypress and click actions.\n *\n * @param {object} elem\n * @param {function} callback\n * @returns {*}\n */\nconst handleAction = function(elem, callback) {\n return elem.on('click keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode)) {\n e.preventDefault();\n } else {\n return;\n }\n }\n\n callback();\n e.preventDefault();\n });\n};\n\n/**\n * Setting up element edibility.\n *\n * @param {object} elem\n * @param {function} callback\n * @param {function} callBeforeOnKeyEditing\n * @returns {*}\n */\nconst handleEditableAction = function(elem, callback, callBeforeOnKeyEditing) {\n if (elem.is(':editable')) {\n throw new Error('handleEditableAction - must be called before setting the element as editable');\n }\n\n // Can't use on(edit) here because we want to do actions (save cache) before the control goes into edit mode\n return elem.on('dblclick keypress', function(e) {\n if (e.type == 'keypress') {\n if (isAriaTriggerKey(e.keyCode) && !elem.is(':editing')) {\n e.preventDefault();\n if (callBeforeOnKeyEditing) {\n callback();\n }\n elem.editable('open');\n if (callBeforeOnKeyEditing) {\n return;\n }\n } else {\n return;\n }\n }\n\n callback();\n });\n};\n\n/**\n * The default function of the module, which does the setup of the page.\n *\n * @param {object} settings\n */\nexport default function(settings) {\n // An array of strings to load as a batch later.\n // Not necessary, but used to load all the strings in one ajax call.\n var strings = {\n default_column_heading: '',\n post_button_text: '',\n cancel_button_text: '',\n remove_note_title: '',\n remove_note_text: '',\n remove_column_title: '',\n note_changed_title: '',\n note_changed_text: '',\n note_deleted_text: '',\n rate_note_title: '',\n rate_note_text: '',\n rate_remove_note_text: '',\n Ok: '',\n delete: '',\n Cancel: '',\n warning: '',\n modal_title_new: '',\n modal_title_edit: '',\n option_youtube: '',\n option_image: '',\n option_link: '',\n\n aria_newcolumn: '',\n aria_newpost: '',\n aria_deletecolumn: '',\n aria_movecolumn: '',\n aria_deletepost: '',\n aria_movepost: '',\n aria_editpost: '',\n aria_addmedia: '',\n aria_addmedianew: '',\n aria_deleteattachment: '',\n aria_postedit: '',\n aria_canceledit: '',\n aria_postnew: '',\n aria_cancelnew: '',\n aria_ratepost: '',\n\n invalid_file_extension: '',\n invalid_file_size_min: '',\n invalid_file_size_max: '',\n\n invalid_youtube_url: '',\n };\n\n // Json decode the strings from the settings.\n var options = JSON.parse(settings.settings) || {};\n var board = options.board || {};\n var contextid = options.contextid;\n\n const MEDIA_SELECTION_BUTTONS = 1,\n ATTACHMENT_VIDEO = 1,\n ATTACHMENT_IMAGE = 2,\n ATTACHMENT_LINK = 3,\n SORTBY_DATE = 1,\n SORTBY_RATING = 2,\n SORTBY_NONE = 3;\n\n var reloadTimer = null,\n lastHistoryId = null,\n isEditor = options.isEditor || false,\n usersCanEdit = options.usersCanEdit,\n userId = parseInt(options.userId) || -1,\n userFullname = options.userFullname,\n ownerId = parseInt(options.ownerId),\n mediaSelection = options.mediaselection || MEDIA_SELECTION_BUTTONS,\n editingNote = 0,\n isReadOnlyBoard = options.readonly || false,\n showauthorofnote = options.showauthorofnote || false,\n allowshowauthorofnoteonboard = options.allowshowauthorofnoteonboard || false,\n ratingenabled = options.ratingenabled,\n sortby = options.sortby || SORTBY_DATE,\n editModal = null,\n enableblanktarget = (parseInt(options.enableblanktarget) === 1);\n\n /**\n * Helper method to make calls to mod_board external services.\n *\n * @param {string} method\n * @param {array} args\n * @param {function} callback\n * @param {function} failcallback\n */\n var serviceCall = function(method, args, callback, failcallback) {\n if (method !== 'board_history') {\n stopUpdating();\n }\n _serviceCall(method, args, function() {\n if (callback) {\n callback.apply(null, arguments);\n }\n if (method !== 'board_history' && method != 'get_board') {\n updateBoard(true);\n }\n }, failcallback);\n };\n\n /**\n * Returns the jquery element of a given note identifier.\n *\n * @param {number} ident\n * @returns {jQuery}\n */\n var getNote = function(ident) {\n return $(\".board_note[data-ident='\" + ident + \"']\");\n };\n\n /**\n * Returns the jquery element of the note text for the given note element.\n *\n * @method getNoteTextForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteTextForNote = function(note) {\n return $(note).find(\".mod_board_note_text\");\n };\n\n /**\n * Returns the jquery element of the preview for the given note element.\n *\n * @method getNotePreviewForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNotePreviewForNote = (note) => {\n return $(note).find(\".mod_board_preview\");\n };\n\n\n /**\n * Returns the jquery element of the note heading for the given note element.\n *\n * @method getNoteHeadingForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteHeadingForNote = function(note) {\n return $(note).find(\".mod_board_note_heading\");\n };\n\n /**\n * Returns the jquery element of the note border for the given note element.\n *\n * @method getNoteBorderForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteBorderForNote = function(note) {\n return $(note).find(\".mod_board_note_border\");\n };\n\n /**\n * Gets a jquery node for the attachments of a given note.\n *\n * @method getNoteAttachmentsForNote\n * @param {object} note\n * @returns {*|jQuery}\n */\n var getNoteAttachmentsForNote = function(note) {\n return $(note).find(\".mod_board_note_attachment\");\n };\n\n /**\n * Creates text identifier for a given node.\n *\n * @method textIdentifierForNote\n * @param {object} note\n * @returns {null|*|jQuery}\n */\n var textIdentifierForNote = function(note) {\n var noteText = getNoteTextForNote(note).html(),\n noteHeading = getNoteHeadingForNote(note).html(),\n noteAttachment = attachmentDataForNote(note);\n\n if (noteHeading.length > 0) {\n return noteHeading;\n }\n if (noteText.length > 0) {\n return noteText.replace(//gi, \" \").replace(/\\n/g, \" \").split(/\\s+/).slice(0, 5).join(\" \");\n }\n if (noteAttachment.info && noteAttachment.info.length > 0) {\n return noteAttachment.info;\n }\n return null;\n };\n\n /**\n * Update the Aria info for a given note id.\n *\n * @method updateNoteAria\n * @param {number} noteId\n */\n var updateNoteAria = function(noteId) {\n var note = getNote(noteId),\n columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text();\n\n if (noteId) { // New post\n var noteIdentifier = textIdentifierForNote(note),\n deleteNoteString = strings.aria_deletepost.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n\n note.find('.delete_note').attr('aria-label', deleteNoteString).attr('title', deleteNoteString);\n\n var moveNoteString = strings.aria_movepost.replace('{post}', noteIdentifier);\n note.find('.move_note').attr('aria-label', moveNoteString).attr('title', moveNoteString);\n\n var editNoteString = strings.aria_editpost.replace('{post}', noteIdentifier);\n note.find('.edit_note').attr('aria-label', editNoteString).attr('title', editNoteString);\n\n note.find('.mod_board_rating').attr('aria-label', strings.aria_ratepost.replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier));\n note.find('.note_ariatext').html(noteIdentifier);\n }\n\n };\n\n /**\n * Update the Aria information for a given column id.\n *\n * @method updateColumnAria\n * @param {number} columnId\n */\n var updateColumnAria = function(columnId) {\n var column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n newNoteString = strings.aria_newpost.replace('{column}', columnIdentifier),\n moveColumnString = strings.aria_movecolumn.replace('{column}', columnIdentifier),\n deleteColumnString = strings.aria_deletecolumn.replace('{column}', columnIdentifier);\n column.find('.newnote').attr('aria-label', newNoteString).attr('title', newNoteString);\n column.find('.mod_column_move').attr('aria-label', moveColumnString).attr('title', moveColumnString);\n column.find('.delete_column').attr('aria-label', deleteColumnString).attr('title', deleteColumnString);\n\n column.find(\".board_note\").each(function(index, note) {\n updateNoteAria($(note).data('ident'));\n });\n };\n\n /**\n * Stop the current note editing process.\n *\n * @method stopNoteEdit\n */\n var stopNoteEdit = function() {\n if (!editingNote) {\n getNote(0).remove();\n return;\n }\n\n var note = getNote(editingNote);\n\n if (note) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n }\n\n editingNote = 0;\n };\n\n /**\n * Start the editing of a particular note, by identifier.\n *\n * @method startNoteEdit\n * @param {number} ident\n */\n var startNoteEdit = function(ident) {\n\n if (editingNote) {\n if (editingNote == ident) {\n return;\n }\n stopNoteEdit();\n }\n\n if (ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n var note = getNote(ident);\n if (note) {\n showModalForm(note);\n\n if (ident) {\n editingNote = ident;\n }\n }\n };\n\n /**\n * Delete a given note, by identifier.\n *\n * @method deleteNote\n * @param {number} ident\n */\n var deleteNote = function(ident) {\n Notification.confirm(\n strings.remove_note_title, // Are you sure?\n strings.remove_note_text, // This will effect others.\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_note', { id: ident }, function (result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n let note = getNote(ident);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n }\n });\n }\n );\n };\n\n /**\n * This function gets a board column as a jQuery element.\n * @param {number} columnID The column ID.\n * @returns {jQuery}\n */\n const getColumn = (columnID) => {\n return $(`.board_column[data-ident='${columnID}'] .board_column_content`);\n };\n\n const sortAfterDelete = (columnID, sortorder) => {\n let column = getColumn(columnID);\n let elements = column.children().filter((_, element) => {\n return parseInt($(element).data('sortorder')) > parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so - 1);\n });\n };\n\n /**\n * Rate (star) a give note, by identifier.\n *\n * @method rateNote\n * @param {number} ident\n */\n var rateNote = function(ident) {\n if (!ratingenabled) {\n return;\n }\n if (isReadOnlyBoard) {\n return;\n }\n\n var note = getNote(ident),\n rating = note.find('.mod_board_rating');\n if (rating.data('disabled')) {\n return;\n }\n rating.data('disabled', true);\n\n serviceCall('can_rate_note', {id: ident}, function(result) {\n if (result.canrate) {\n const rateRemoveText = result.hasrated ? strings.rate_remove_note_text : strings.rate_note_text;\n Notification.confirm(\n strings.rate_note_title,\n rateRemoveText, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n serviceCall('rate_note', {id: ident}, function(result) {\n if (result.status) {\n lastHistoryId = result.historyid;\n rating.html(` ${result.rating} `);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n rating.data('disabled', false);\n });\n }\n ).then(function(rateModal) {\n // Do this here, because it catches both cancel clicks, or someone clicking the X.\n rateModal.getRoot().on(ModalEvents.hidden, function() {\n rating.data('disabled', false);\n });\n });\n }\n });\n };\n\n /**\n * Update the attachment information of a note.\n *\n * @method attachmentTypeChanged\n * @param {object} note\n */\n var attachmentTypeChanged = function(note) {\n var noteAttachment = getNoteAttachmentsForNote(note),\n type = noteAttachment.find('.mod_board_type').val(),\n attachmentInfo = noteAttachment.find('.info'),\n attachmentUrl = noteAttachment.find('.url'),\n attachmentFile = noteAttachment.find('.mod_board_file');\n\n if (type > \"0\") {\n attachmentInfo.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_info']);\n attachmentUrl.prop('placeholder', strings['option_' + attachmentTypeToString(type) + '_url']);\n\n attachmentInfo.show();\n if (type == ATTACHMENT_IMAGE && FileReader) {\n attachmentFile.show();\n attachmentUrl.hide();\n } else {\n attachmentFile.hide();\n attachmentUrl.show();\n }\n } else {\n attachmentInfo.hide();\n attachmentUrl.hide();\n attachmentFile.hide();\n\n attachmentInfo.val('');\n attachmentUrl.val('');\n\n }\n };\n\n /**\n * Set the attachment of a note.\n *\n * @method setAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var setAttachment = function(note, attachment) {\n var noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment) {\n if (!attachment) {\n attachment = {type: \"0\"};\n } else {\n attachment.type += \"\";// Just in case\n }\n var attType = noteAttachment.find('.mod_board_type');\n attType.val(attachment.type ? attachment.type : \"0\");\n if (attType.val() > \"0\") {\n noteAttachment.find('.info').val(decodeText(attachment.info));\n noteAttachment.find('.url').val(decodeText(attachment.url));\n }\n attachmentTypeChanged(note, attachment);\n }\n previewAttachment(note, attachment);\n };\n\n /**\n * Returns an object with various information about a note's attachment.\n *\n * @method attachmentDataForNote\n * @param {object} note\n * @returns {{filename: null, filecontents: null, type: number, url: null, info: null}}\n */\n var attachmentDataForNote = function(note) {\n var attachment = {type: 0, info: null, url: null, filename: null, filecontents: null},\n noteAttachment = getNoteAttachmentsForNote(note);\n if (noteAttachment.length) {\n attachment.type = noteAttachment.find('.mod_board_type').val();\n attachment.info = encodeText(noteAttachment.find('.info').val());\n attachment.url = encodeText(noteAttachment.find('.url').val());\n var fileElem = noteAttachment.find('.mod_board_file>input');\n if (fileElem.data('filename')) {\n attachment.filename = fileElem.data('filename');\n attachment.filecontents = fileElem.data('filecontents');\n }\n }\n if ((!attachment.info || !attachment.info.length) && (!attachment.url || !attachment.url.length) &&\n (!attachment.filename)) {\n attachment.type = 0;\n }\n\n return attachment;\n };\n\n /**\n * Get the string type of a attachment type number.\n *\n * @method attachmentTypeToString\n * @param {number} type\n * @returns {string|null}\n */\n var attachmentTypeToString = function(type) {\n switch (type) {\n case \"1\": return 'youtube';\n case \"2\": return 'image';\n case \"3\": return 'link';\n default: return null;\n }\n };\n\n /**\n * This parses a youtube video ID from a URL. We can use this ID to\n * construct the embed URL.\n * @param {string} url The URL entered to the modal.\n * @returns {string | null} The youtube embed URL or null.\n */\n const getEmbedUrl = (url) => {\n // Thanks for the regex from: https://gist.github.com/rodrigoborgesdeoliveira/987683cfbfcc8d800192da1e73adc486.\n let regex = /(\\/|%3D|v=)([0-9A-z-_]{11})([%#?&]|$)/;\n let videoID = url.match(regex);\n if (!videoID || videoID[2] === undefined || videoID[2].length !== 11) {\n return null;\n }\n return `https://www.youtube-nocookie.com/embed/${videoID[2]}`;\n };\n\n /**\n * Display the attachment preview for a note.\n *\n * @method previewAttachment\n * @param {object} note\n * @param {object} attachment\n */\n var previewAttachment = function(note, attachment) {\n var elem = note.find('.mod_board_preview');\n if (!attachment) {\n attachment = attachmentDataForNote(note);\n }\n\n if (!getNoteTextForNote(note).html().length) {\n elem.addClass('mod_board_notext');\n } else {\n elem.removeClass('mod_board_notext');\n }\n\n elem.removeClass('wrapper_youtube');\n elem.removeClass('wrapper_image');\n elem.removeClass('wrapper_url');\n if (attachment.filename && parseInt(attachment.type) == ATTACHMENT_IMAGE) { // Before uploading\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n } else if (attachment.url) {\n const blanktarget = enableblanktarget ? ' target=\"_blank\"' : '';\n switch (parseInt(attachment.type)) {\n case ATTACHMENT_VIDEO: { // Youtube\n let url = getEmbedUrl(attachment.url);\n if (url === null) {\n elem.html(strings.invalid_youtube_url);\n } else {\n elem.html('');\n elem.addClass('wrapper_youtube').addClass('position-relative');\n }\n elem.show();\n }\n break;\n case ATTACHMENT_IMAGE: // Image\n elem.html(`\"${attachment.info}\"\n`);\n elem.addClass('wrapper_image');\n elem.show();\n break;\n case ATTACHMENT_LINK: // Url\n elem.html('' +\n (attachment.info || attachment.url) + '');\n elem.addClass('wrapper_url');\n elem.show();\n break;\n default:\n elem.html('');\n elem.hide();\n }\n } else {\n elem.html('');\n elem.hide();\n }\n };\n\n /**\n * Add a new note with the given information.\n *\n * @method addNote\n * @param {number} columnid\n * @param {number} ident\n * @param {string} heading\n * @param {string} content\n * @param {object} attachment\n * @param {object} owner the owner of the note containing the userid as id and the owner fullname\n * @param {number} sortorder\n * @param {string} rating\n */\n var addNote = function(columnid, ident, heading, content, attachment, owner, sortorder, rating) {\n var ismynote = owner.id == userId || !ident;\n var iseditable = isEditor || (ismynote && !isReadOnlyBoard);\n\n if (!ident) {\n var pendingNote = getNote(0);\n if (pendingNote) {\n pendingNote.remove();\n }\n }\n\n // Making space for this note if necessary in the sort order.\n if (sortby == SORTBY_NONE) {\n let children = $(`.board_column[data-ident='${columnid}'] .board_column_content`).children();\n let elements = children.filter((_, element) => {\n return parseInt($(element).data('sortorder')) >= parseInt(sortorder);\n });\n elements.each((_, element) => {\n let so = $(element).data('sortorder');\n $(element).data('sortorder', so + 1);\n });\n }\n\n var note = $('
');\n if (ismynote) {\n note.addClass('mod_board_mynote');\n }\n if (iseditable) {\n note.addClass('mod_board_editablenote');\n }\n if (!ismynote && !iseditable) {\n note.addClass('mod_board_nosort');\n }\n\n var notecontent = $('
'),\n notecontrols = $('
'),\n noteHeading = $('
' + (heading ? heading : '') + '
'),\n noteAuthorusername = $(''),\n noteBorder = $('
'),\n noteText = $('
' + (content ? content : '') + '
'),\n noteAriaText = $('
'),\n attachmentPreview = $('
');\n\n if (allowshowauthorofnoteonboard == true && showauthorofnote == true) {\n let fullname = '';\n if (ismynote) {\n // Use the Name of the user itself. We do not need to get this information from somewhere else.\n fullname = userFullname;\n } else {\n fullname = owner.fullname;\n }\n\n noteAuthorusername = '
' +\n ' ' +\n '' +\n fullname +\n '' +\n '
' ;\n }\n\n notecontent.append(noteHeading);\n notecontent.append(noteAuthorusername);\n notecontent.append(noteBorder);\n notecontent.append(noteText);\n notecontent.append(noteAriaText);\n\n notecontent.append(attachmentPreview);\n note.append(notecontent);\n\n var columnContent = $('.board_column[data-ident=' + columnid + '] .board_column_content');\n\n var beginEdit = () => {\n startNoteEdit(ident);\n };\n\n if (ident) {\n if (ratingenabled) {\n note.addClass('mod_board_rateablenote');\n var rateElement = $(`
${rating}
`);\n\n handleAction(rateElement, () => {\n rateNote(ident);\n });\n notecontrols.append(rateElement);\n }\n\n if (iseditable) {\n var removeElement = $('
');\n handleAction(removeElement, () => {\n deleteNote(ident);\n });\n\n notecontrols.append(removeElement);\n\n if (usersCanEdit == 1 || isEditor) {\n var moveElement = $('
');\n notecontrols.append(moveElement);\n moveNotesDialog.init(ownerId, moveNote);\n }\n\n var editElement = $('
');\n notecontrols.append(editElement);\n handleAction(editElement, () => {\n beginEdit();\n });\n updateSortable();\n setAttachment(note, attachment);\n } else {\n previewAttachment(note, attachment);\n }\n\n note.append(notecontrols);\n\n handleAction(notecontent, () => fullScreenNote(ident, notecontent));\n\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n\n var lastOne = columnContent.find(\".board_note\").last();\n\n if (lastOne.length) {\n note.insertAfter(lastOne);\n } else {\n columnContent.prepend(note);\n }\n } else {\n $('.board_column[data-ident=' + columnid + '] .board_column_newcontent').append(note);\n // This is effectively a note placeholder. So we don't need to show it.\n note.hide();\n beginEdit();\n }\n };\n\n /**\n * Add a new column.\n *\n * @method addColumn\n * @param {object} ident\n * @param {string} name\n * @param {bool} locked\n * @param {array} notes\n * @param {string} colour\n */\n var addColumn = function(ident, name, locked, notes, colour) {\n let headerStyle = `style=\"border-top: 10px solid #${colour}\"`;\n var iseditable = isEditor,\n nameCache = null,\n column = $(`
`),\n columnHeader = $('
'),\n columnSort = $('
'),\n columnName = $('
' + name + '
'),\n columnContent = $('
'),\n columnNewContent = $('
');\n // Only add the sort button if it makes sense.\n if (sortby != SORTBY_NONE) {\n columnHeader.append(columnSort);\n }\n columnHeader.append(columnName);\n\n if (options.hideheaders) {\n columnName.addClass('d-none');\n }\n\n columnSort.on('click', function() {\n sortNotes(columnContent, true);\n });\n\n if (iseditable) {\n column.addClass('mod_board_editablecolumn');\n const lockIcon = locked ? 'fa-lock' : 'fa-unlock';\n const lockElement = $(`
`);\n const lockstring = locked ? 'aria_column_locked' : 'aria_column_unlocked';\n getString(lockstring, 'mod_board', name).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n\n handleAction(lockElement, () => {\n const lockColumn = column.attr('data-locked') !== 'true';\n serviceCall('lock_column', {id: ident, status: lockColumn}, function(result) {\n const columnName = column.find('.mod_board_column_name').text();\n if (result.status) {\n if (lockColumn) {\n lockElement.removeClass('fa-unlock').addClass('fa-lock');\n column.attr('data-locked', 'true');\n column.find('.board_button.newnote').addClass('d-none');\n getString('aria_column_locked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n } else {\n lockElement.removeClass('fa-lock').addClass('fa-unlock');\n column.attr('data-locked', 'false');\n column.find('.board_button.newnote').removeClass('d-none');\n getString('aria_column_unlocked', 'mod_board', columnName).done(function(str) {\n lockElement.attr('aria-label', str);\n lockElement.attr('title', str);\n });\n }\n lastHistoryId = result.historyid;\n updateSortable();\n }\n });\n });\n columnHeader.append(lockElement);\n\n columnHeader.addClass('icon-size-3');\n const moveElement = $('
');\n columnHeader.append(moveElement);\n moveColumnsDialog.init(moveColumn);\n var removeElement = $('
');\n handleAction(removeElement, () => {\n Notification.confirm(\n strings.remove_column_title, // Are you sure?\n getString('remove_column_text', 'mod_board', getColumnName(ident)),\n strings.delete,\n strings.Cancel,\n function() {\n serviceCall('delete_column', {id: ident}, function(result) {\n if (result.status) {\n column.remove();\n lastHistoryId = result.historyid;\n }\n });\n }\n );\n });\n\n columnHeader.append(removeElement);\n }\n\n column.append(columnHeader);\n column.append(columnContent);\n column.append(columnNewContent);\n\n if (iseditable) {\n handleEditableAction(columnName, function() {\n nameCache = columnName.html();\n }, true);\n\n columnName.editable({\n toggleFontSize: false,\n closeOnEnter: true,\n callback: function(data) {\n if (data.content) {\n serviceCall('update_column', {id: ident, name: columnName.html()}, function(result) {\n if (!result.status) {\n columnName.html(nameCache);\n nameCache = null;\n } else {\n lastHistoryId = result.historyid;\n updateColumnAria(ident);\n }\n }, function() {\n columnName.html(nameCache);\n nameCache = null;\n });\n } else {\n columnName.html(nameCache);\n nameCache = null;\n }\n }\n });\n }\n\n if (!isReadOnlyBoard) {\n const newNoteButton = $('
' +\n '
');\n columnNewContent.append(newNoteButton);\n if (column.attr('data-locked') === 'true') {\n newNoteButton.addClass('d-none');\n }\n handleAction(columnNewContent.find('.newnote'), function() {\n // We do not need to add fullname to the owner because we use ismynote and the fullname of the actual board user.\n addNote(ident, 0, null, null, null, {id: userId}, 0, 0);\n });\n }\n\n var lastOne = $(\".mod_board .board_column_hasdata\").last();\n if (lastOne.length) {\n column.insertAfter(lastOne);\n } else {\n $(\".mod_board\").append(column);\n }\n\n if (notes) {\n for (var index in notes) {\n let sortorder = sortby == 3 ? notes[index].sortorder : notes[index].timecreated;\n\n addNote(ident, notes[index].id, notes[index].heading, notes[index].content,\n {type: notes[index].type, info: notes[index].info, url: notes[index].url},\n {id: notes[index].userid, fullname: notes[index].fullname},\n sortorder, notes[index].rating);\n }\n }\n sortNotes(columnContent);\n updateColumnAria(ident);\n if (isEditor || usersCanEdit == 1) {\n updateSortable();\n }\n if (isEditor) {\n columnSorting();\n }\n };\n\n /**\n * Gets the text name used in the heading of a column.\n * @param {number} id The ID data attribute on the column element.\n * @returns {string}\n */\n const getColumnName = (id) => {\n return $(`.board_column[data-ident='${id}']`).find('.mod_board_column_name').html();\n };\n\n /**\n * Add the new column button.\n *\n * @method addNewColumnButton\n */\n var addNewColumnButton = function() {\n var column = $('
'),\n newBusy = false;\n column.append('
');\n\n handleAction(column.find('.newcolumn'), function() {\n if (newBusy) {\n return;\n }\n newBusy = true;\n\n serviceCall('add_column', {boardid: board.id, name: strings.default_column_heading}, function(result) {\n addColumn(result.id, strings.default_column_heading, false, {}, selectHeadingColour());\n lastHistoryId = result.historyid;\n newBusy = false;\n }, function() {\n newBusy = false;\n });\n });\n\n $(\".mod_board\").append(column);\n };\n\n /**\n * This selects the next heading colour from options based on the count of the\n * current columns. Length of decremented by one as the new column button is\n * also denoted as a column.\n * @returns {string} colour hex string.\n */\n const selectHeadingColour = () => {\n let colCount = $('.board_column').length - 1;\n let colourCount = options.colours.length;\n return options.colours[colCount % colourCount];\n };\n\n /**\n * Update a note with the provided information.\n *\n * @method updateNote\n * @param {object} note\n * @param {string} heading\n * @param {object} data\n */\n var updateNote = function(note, heading, data) {\n var noteHeading = getNoteHeadingForNote(note);\n var noteText = getNoteTextForNote(note);\n var noteBorder = getNoteBorderForNote(note);\n\n noteText.html(data.content);\n noteHeading.html(data.heading);\n setAttachment(note, data.attachment);\n updateNoteAria(data.id);\n\n // Reset the visibility state.\n noteHeading.show();\n noteBorder.show();\n noteText.show();\n if (!noteHeading.html()) {\n noteHeading.hide();\n noteBorder.hide();\n }\n if (!noteText.html() && noteHeading.html()) {\n noteText.hide();\n noteBorder.hide();\n }\n };\n\n /**\n * Fetch and process the recent board history.\n *\n * @method processBoardHistory\n */\n var processBoardHistory = function() {\n serviceCall('board_history', {id: board.id, ownerid: ownerId, since: lastHistoryId}, function(boardhistory) {\n for (var index in boardhistory) {\n var item = boardhistory[index];\n if (item.boardid != board.id) {\n continue; // Hmm\n }\n\n var data = JSON.parse(item.content);\n if (item.action == 'add_note') {\n // This is called on a board if someone else has added a note in a different browser.\n let sortorder = sortby == 3 ? data.sortorder : data.timecreated;\n addNote(data.columnid, data.id, data.heading, data.content, data.attachment,\n {id: item.userid , fullname: item.userid + \" \" + item.fullname}, sortorder, data.rating);\n updateNoteAria(data.id);\n sortNotes($('.board_column[data-ident=' + data.columnid + '] .board_column_content'));\n } else if (item.action == 'update_note') {\n // This is called on a board if someone else has updated a note in a different browser.\n let note = getNote(data.id),\n formModal = editModal,\n historyData = data;\n if (note) {\n let noteHeading = getNoteHeadingForNote(note);\n\n if (editingNote == data.id) {\n Notification.confirm(\n strings.note_changed_title, // Confirm.\n strings.note_changed_text, // Are you sure?\n strings.Ok,\n strings.Cancel,\n function() {\n formModal.hide();\n updateNote(note, noteHeading, historyData);\n stopNoteEdit();\n }\n );\n } else {\n updateNote(note, noteHeading, data);\n }\n }\n } else if (item.action == 'delete_note') {\n if (editingNote == data.id) {\n Notification.alert(strings.warning, strings.note_deleted_text);\n stopNoteEdit();\n }\n let note = getNote(data.id);\n if (sortby == SORTBY_NONE) {\n let columnID = note.data('column');\n let sortorder = note.data('sortorder');\n sortAfterDelete(columnID, sortorder);\n }\n note.remove();\n\n } else if (item.action == 'add_column') {\n addColumn(data.id, data.name, false, {}, selectHeadingColour());\n } else if (item.action == 'move_column') {\n const board = $('.mod_board');\n data.sortorder.forEach(column => {\n const columnElement = board.find(`.board_column[data-ident='${column}']`);\n columnElement.detach().appendTo(board);\n });\n } else if (item.action == 'update_column') {\n $(\".board_column[data-ident='\" + data.id + \"'] .mod_board_column_name\").html(data.name);\n updateColumnAria(data.id);\n } else if (item.action == 'lock_column') {\n $(\".board_column[data-ident='\" + data.id + \"']\").attr(\"data-locked\", data.locked);\n if (data.locked) {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').addClass('d-none');\n } else {\n $(\".board_column[data-ident='\" + data.id + \"']\").find('.board_button.newnote').removeClass('d-none');\n }\n updateSortable();\n } else if (item.action == 'delete_column') {\n var column = $(\".board_column[data-ident='\" + data.id + \"']\");\n if (editingNote && column.find('.board_note[data-ident=\"' + editingNote + '\"]').length) {\n stopNoteEdit();\n }\n column.remove();\n } else if (item.action == 'rate_note') {\n var note = getNote(data.id);\n note.find('.mod_board_rating').html(data.rating);\n if (sortby == SORTBY_RATING) {\n sortNotes(note.closest('.board_column_content'));\n }\n }\n lastHistoryId = item.id;\n }\n\n updateBoard();\n });\n };\n\n /**\n * Trigger a board update.\n *\n * @method updateBoard\n * @param {boolean} instant\n */\n var updateBoard = function(instant) {\n if (instant) {\n processBoardHistory();\n } else if (options.history_refresh > 0) {\n if (reloadTimer) {\n stopUpdating();\n }\n reloadTimer = setTimeout(processBoardHistory, options.history_refresh * 1000);\n }\n };\n\n /**\n * Stop/prevent the board reload timer from firing.\n *\n * @method stopUpdating\n */\n var stopUpdating = function() {\n clearTimeout(reloadTimer);\n reloadTimer = null;\n };\n\n /**\n * Sort a set of notes.\n *\n * @sortNotes\n * @param {string} content\n * @param {boolean} toggle\n */\n var sortNotes = function(content, toggle) {\n var sortCol = $(content).parent().find('.mod_board_column_sort'),\n direction = $(content).data('sort');\n if (!direction) {\n if (sortby == SORTBY_RATING) {\n direction = 'desc';\n } else {\n direction = 'asc';\n }\n }\n if (toggle) {\n direction = direction == 'asc' ? 'desc' : 'asc';\n }\n\n if (direction == 'asc') {\n sortCol.removeClass('fa-angle-down');\n sortCol.addClass('fa-angle-up');\n } else {\n sortCol.removeClass('fa-angle-up');\n sortCol.addClass('fa-angle-down');\n }\n $(content).data('sort', direction);\n\n var desc,\n asc;\n if (sortby == SORTBY_DATE) {\n desc = function(a, b) {\n return $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_RATING) {\n desc = function(a, b) {\n return $(b).find('.mod_board_rating').text() - $(a).find('.mod_board_rating').text() ||\n $(b).data(\"sortorder\") - $(a).data(\"sortorder\");\n };\n asc = function(a, b) {\n return $(a).find('.mod_board_rating').text() - $(b).find('.mod_board_rating').text() ||\n $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n } else if (sortby == SORTBY_NONE) {\n let sortElements = (a, b) => {\n return $(a).data(\"sortorder\") - $(b).data(\"sortorder\");\n };\n $('> .board_note', $(content)).sort(sortElements).appendTo($(content));\n return;\n }\n\n $('> .board_note', $(content)).sort(direction === 'asc' ? asc : desc).appendTo($(content));\n\n };\n\n /**\n * Update sorting of sortable content.\n *\n * @method updateSortable\n */\n var updateSortable = function() {\n let fromColumnID;\n $(\".board_column[data-locked='false'] .board_column_content\").sortable({\n connectWith: \".board_column[data-locked='false'] .board_column_content\",\n cancel: \".mod_board_nosort\",\n handle: \".move_note\",\n start: function(_, ui) {\n fromColumnID = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n var note = $(ui.item),\n tocolumn = note.closest('.board_column'),\n elem = $(this),\n noteid = note.data('ident'),\n columnid = tocolumn.data('ident');\n let columnElements = tocolumn.find('.board_column_content').children();\n let sortorder = columnElements.index($(`.board_note[data-ident=${noteid}]`));\n let payload = {\n id: noteid,\n columnid: columnid,\n ownerid: ownerId,\n sortorder: sortorder\n };\n moveNote(fromColumnID, payload, elem);\n }\n });\n };\n\n /**\n * Move a note to a new position / column.\n *\n * @param {Int} fromColumnID The column the note is being moved from.\n * @param {Object} payload The payload to send to the server.\n * @param {Domnode} elem The element clicked to trigger the move.\n */\n const moveNote = (fromColumnID, payload, elem) => {\n updateSortOrders(fromColumnID, payload.columnid, payload.id, payload.sortorder);\n\n serviceCall('move_note', payload, (result) => {\n if (result.status) {\n lastHistoryId = result.historyid;\n updateNoteAria(payload.id);\n updateBoard();\n sortNotes($(`.board_column[data-ident=${payload.columnid}] .board_column_content`));\n } else {\n if (elem) {\n elem.sortable('cancel');\n }\n }\n });\n };\n\n /**\n * Enable column sorting\n */\n const columnSorting = () => {\n let movingColumnId;\n $(\".mod_board\").sortable({\n connectWith: \".mod_board\",\n axis: \"x\",\n containment: \".mod_board_wrapper\",\n cancel: \".mod_board_nosort\",\n handle: \".mod_column_move\",\n start: function(_, ui) {\n movingColumnId = $(ui.item).closest('.board_column').data('ident');\n },\n stop: function(_, ui) {\n let column = $(ui.item);\n let columns = $(\".mod_board\").find('.board_column');\n let sortorder = columns.index(column);\n let payload = {\n id: movingColumnId,\n sortorder: sortorder\n };\n moveColumn(payload);\n }\n });\n };\n\n /**\n * Move a column to a new position.\n *\n * @param {Object} payload The payload to send to the server.\n */\n const moveColumn = (payload) => {\n serviceCall('move_column', payload, false);\n };\n\n /**\n * Updates the inline data attributes necessary for rendering the lists\n * in the correct sort order. Note: the data attribute values updated by\n * jQuery are not reflected in DOM inspection but are still set.\n * @param {number} fromColumnID The column ID of the column to sort.\n * @param {number} toColumnID The column ID of the column to sort.\n * @param {number} noteID The note ID that was moved.\n * @param {number} newSortOrder The new position of the note sort order.\n */\n const updateSortOrders = (fromColumnID, toColumnID, noteID, newSortOrder) => {\n let toColumn = $(`.board_column[data-ident=${toColumnID}] .board_column_content`);\n let movedNote = $(`.board_note[data-ident=${noteID}]`);\n let oldSortOrder = movedNote.data('sortorder');\n // Check whether it is the same column and then increment or decrement notes above or below\n // then set sortorder according to whether the sortorder has moved up or down.\n let toChildren = toColumn.children();\n if (fromColumnID == toColumnID) {\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (oldSortOrder < newSortOrder) {\n if (sortOrder <= newSortOrder && sortOrder >= oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n } else if (oldSortOrder > newSortOrder) {\n if (sortOrder >= newSortOrder && sortOrder <= oldSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n }\n });\n } else {\n let fromColumn = $(`.board_column[data-ident=${fromColumnID}] .board_column_content`);\n let fromChildren = fromColumn.children();\n toChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder >= newSortOrder) {\n $(note).data('sortorder', sortOrder + 1);\n }\n });\n fromChildren.each((_, note) => {\n let sortOrder = $(note).data('sortorder');\n if (sortOrder > oldSortOrder) {\n $(note).data('sortorder', sortOrder - 1);\n }\n });\n }\n movedNote.data('sortorder', newSortOrder);\n };\n\n /**\n * Get the body fragment for the modal form.\n *\n * @param {number} noteid\n * @param {number} columnid\n * @param {number} ownerId\n * @returns {Deferred|*}\n */\n var getBody = function(noteid, columnid, ownerId) {\n // Get the content of the modal.\n var params = {noteid: noteid, columnid: columnid, ownerid: ownerId};\n return Fragment.loadFragment('mod_board', 'note_form', contextid, params);\n };\n\n /**\n * Setup the aria labels for the modal.\n *\n * @param {object} note\n * @param {object} modal\n */\n var updateModalAria = function(note, modal) {\n let columnIdentifier = note.closest('.board_column').find('.mod_board_column_name').text(),\n addYoutube,\n addImage,\n addLink,\n postButton,\n cancelButton,\n modalRoot = modal.getRoot();\n\n if (note.data('ident')) {\n // Is a note update.\n var noteIdentifier = textIdentifierForNote(note);\n\n postButton = strings.aria_postedit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n cancelButton = strings.aria_canceledit.replace('{column}', columnIdentifier).replace('{post}', noteIdentifier);\n addYoutube = strings.aria_addmedia.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addImage = strings.aria_addmedia.replace('{type}', strings.option_image).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n addLink = strings.aria_addmedia.replace('{type}', strings.option_link).replace('{column}',\n columnIdentifier).replace('{post}', noteIdentifier);\n } else {\n // Note is new.\n postButton = strings.aria_postnew.replace('{column}', columnIdentifier);\n cancelButton = strings.aria_cancelnew.replace('{column}', columnIdentifier);\n addYoutube = strings.aria_addmedianew.replace('{type}', strings.option_youtube).replace('{column}',\n columnIdentifier);\n addImage = strings.aria_addmedianew.replace('{type}', strings.option_image).replace('{column}', columnIdentifier);\n addLink = strings.aria_addmedianew.replace('{type}', strings.option_link).replace('{column}', columnIdentifier);\n }\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('aria-label', addYoutube);\n modalRoot.find('.mod_board_attachment_button.youtube_button').attr('title', addYoutube);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('aria-label', addImage);\n modalRoot.find('.mod_board_attachment_button.image_button').attr('title', addImage);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('aria-label', addLink);\n modalRoot.find('.mod_board_attachment_button.link_button').attr('title', addLink);\n }\n\n let button = modalRoot.find(modal.getActionSelector('save'));\n if (button) {\n button.attr('aria-label', postButton);\n }\n button = modalRoot.find(modal.getActionSelector('cancel'));\n if (button) {\n button.attr('aria-label', cancelButton);\n }\n };\n\n /**\n * Displays the modal form to edit a note.\n *\n * @param {object} note\n */\n var showModalForm = function(note) {\n let noteId = 0,\n columnId = note.data('column'),\n column = $('.board_column[data-ident=' + columnId + ']'),\n columnIdentifier = column.find('.mod_board_column_name').text(),\n title;\n\n if (note.data('ident')) {\n noteId = note.data('ident');\n title = strings.modal_title_edit.replace('{column}', columnIdentifier);\n } else {\n title = strings.modal_title_new.replace('{column}', columnIdentifier);\n }\n\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: title,\n body: getBody(noteId, columnId, ownerId),\n large: true,\n removeOnClose: true\n }).then(function(modal) {\n // Use the body promise so we know body content is loaded.\n modal.getBodyPromise().then(function () {\n let saveInProgress = false;\n editModal = modal;\n modal.setLarge();\n modal.setSaveButtonText(strings.post_button_text);\n modal.setButtonText('cancel', strings.cancel_button_text);\n\n modal.getRoot().on(ModalEvents.hidden, function () {\n stopNoteEdit();\n if (!note.data('ident')) {\n note.remove();\n }\n });\n\n modal.getRoot().on(ModalEvents.save, function (e) {\n e.preventDefault();\n modal.getRoot().find('form').submit();\n });\n\n var changeEvent = document.createEvent('HTMLEvents');\n changeEvent.initEvent('change', true, true);\n\n modal.getRoot().on('submit', 'form', function (e) {\n e.preventDefault();\n\n // Prevent multiple form submissions from being sent.\n if (saveInProgress) {\n return;\n }\n saveInProgress = true;\n\n // First, make sure the native html5 validity checks are run.\n let valid = modal.getRoot().find('form').get(0).reportValidity();\n if (!valid) {\n saveInProgress = false;\n return;\n }\n\n // Prompt all inputs to run their validation functions.\n // Normally this would happen when the form is submitted, but\n // since we aren't submitting the form normally we need to run client side\n // validation.\n modal.getRoot().find(':input').each(function (index, element) {\n element.dispatchEvent(changeEvent);\n });\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n var invalid = $.merge(\n modal.getRoot().find('[aria-invalid=\"true\"]'),\n modal.getRoot().find('.error'),\n modal.getRoot().find(':invalid')\n );\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n saveInProgress = false;\n return;\n }\n\n var formData = JSON.stringify(modal.getRoot().find('form').serialize());\n serviceCall('submit_form', {contextid: contextid, jsonformdata: formData}, function (result) {\n if (result.status) {\n if (result.action == 'insert') {\n // Added a new note.\n lastHistoryId = result.historyid;\n note.remove();\n addNote(columnId, result.note.id, result.note.heading, result.note.content,\n {type: result.note.type, info: result.note.info, url: result.note.url},\n {id: result.note.userid}, result.note.timecreated, result.note.rating);\n sortNotes($('.board_column[data-ident=' + columnId + '] .board_column_content'));\n updateNoteAria(result.note.id);\n } else {\n // Updated existing note.\n lastHistoryId = result.historyid;\n getNoteTextForNote(note).html(result.note.content);\n getNoteHeadingForNote(note).html(result.note.heading);\n updateNoteAria(result.note.id);\n setAttachment(note, {\n type: result.note.type,\n info: result.note.info, url: result.note.url\n });\n }\n stopNoteEdit();\n\n // Clear the form changed checker.\n Y.use('moodle-core-formchangechecker', function() {\n M.core_formchangechecker.reset_form_dirty_state();\n });\n\n modal.destroy();\n } else {\n modal.destroy();\n }\n });\n\n });\n\n if (mediaSelection == MEDIA_SELECTION_BUTTONS) {\n // First hide the select menu.\n modal.getRoot().find('#fitem_id_mediatype').hide();\n\n let mediaSelect = modal.getRoot().find('#fitem_id_mediatype select'),\n ytButton = modal.getRoot().find('.mod_board_attachment_button.youtube_button'),\n pictureButton = modal.getRoot().find('.mod_board_attachment_button.image_button'),\n linkButton = modal.getRoot().find('.mod_board_attachment_button.link_button'),\n updateMediaButtons = function() {\n ytButton.removeClass('selected');\n pictureButton.removeClass('selected');\n linkButton.removeClass('selected');\n switch (mediaSelect.val()) {\n case (\"1\"):\n ytButton.addClass('selected');\n break;\n case (\"2\"):\n pictureButton.addClass('selected');\n break;\n case (\"3\"):\n linkButton.addClass('selected');\n break;\n }\n };\n\n updateMediaButtons();\n handleAction(ytButton, function() {\n if (mediaSelect.val() === \"1\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(1);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(pictureButton, function() {\n if (mediaSelect.val() === \"2\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(2);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n handleAction(linkButton, function() {\n if (mediaSelect.val() === \"3\") {\n mediaSelect.val(0);\n } else {\n mediaSelect.val(3);\n }\n updateMediaButtons();\n mediaSelect[0].dispatchEvent(changeEvent);\n });\n } else {\n modal.getRoot().find('#fitem_id_mediabuttons').hide();\n }\n\n updateModalAria(note, modal);\n modal.show();\n\n return modal;\n }).catch(Notification.exception);\n return modal;\n }).catch(Notification.exception);\n };\n\n /**\n * Show the note in a modal\n * @param {Int} ident The note id\n * @param {Object} notecontent The note content\n */\n var fullScreenNote = (ident, notecontent) => {\n const heading = getNoteHeadingForNote(notecontent).html();\n const modalBody = $(document.createElement('div'));\n modalBody.addClass('mod_board_note_content');\n const text = getNoteTextForNote(notecontent);\n if (text) {\n modalBody.append(text.clone());\n }\n const preview = getNotePreviewForNote(notecontent);\n if (preview) {\n modalBody.append(preview.clone());\n }\n\n // Adds the comments to a note.\n const commentArea = $(document.createElement('div'));\n commentArea.attr('data-region', 'comment-area');\n modalBody.append(commentArea);\n Comments.fetchFor(ident, commentArea);\n\n ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: heading,\n body: modalBody,\n }).then(function(modal) {\n modal.setLarge();\n modal.show();\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function () {\n // Destroy when hidden.\n modal.destroy();\n });\n return modal;\n }, this).catch(Notification.exception);\n };\n\n /**\n * Initialize board.\n *\n * @method init\n */\n var init = function() {\n serviceCall('get_board', {id: board.id, ownerid: ownerId}, function(columns) {\n // Init\n if (columns) {\n for (var index in columns) {\n addColumn(\n columns[index].id,\n columns[index].name,\n columns[index].locked,\n columns[index].notes || {},\n options.colours[columns[index].id % options.colours.length]\n );\n }\n }\n\n if (isEditor) {\n addNewColumnButton();\n }\n\n lastHistoryId = board.historyid;\n\n if (isEditor) {\n updateSortable();\n columnSorting();\n }\n\n updateBoard();\n });\n };\n\n // Get strings\n var stringsInfo = [];\n for (var string in strings) {\n stringsInfo.push({key: string, component: 'mod_board'});\n }\n\n $.when(getStrings(stringsInfo)).done(function(results) {\n var index = 0;\n for (string in strings) {\n strings[string] = results[index++];\n }\n\n init();\n });\n}\n"],"names":["settings","strings","default_column_heading","post_button_text","cancel_button_text","remove_note_title","remove_note_text","remove_column_title","note_changed_title","note_changed_text","note_deleted_text","rate_note_title","rate_note_text","rate_remove_note_text","Ok","delete","Cancel","warning","modal_title_new","modal_title_edit","option_youtube","option_image","option_link","aria_newcolumn","aria_newpost","aria_deletecolumn","aria_movecolumn","aria_deletepost","aria_movepost","aria_editpost","aria_addmedia","aria_addmedianew","aria_deleteattachment","aria_postedit","aria_canceledit","aria_postnew","aria_cancelnew","aria_ratepost","invalid_file_extension","invalid_file_size_min","invalid_file_size_max","invalid_youtube_url","options","JSON","parse","board","contextid","reloadTimer","lastHistoryId","isEditor","usersCanEdit","userId","parseInt","userFullname","ownerId","mediaSelection","mediaselection","editingNote","isReadOnlyBoard","readonly","showauthorofnote","allowshowauthorofnoteonboard","ratingenabled","sortby","editModal","enableblanktarget","serviceCall","method","args","callback","failcallback","stopUpdating","call","methodname","done","data","fail","error","exception","_serviceCall","apply","arguments","updateBoard","getNote","ident","getNoteTextForNote","note","find","getNoteHeadingForNote","getNoteBorderForNote","getNoteAttachmentsForNote","textIdentifierForNote","noteText","html","noteHeading","noteAttachment","attachmentDataForNote","length","replace","split","slice","join","info","updateNoteAria","noteId","columnIdentifier","closest","text","noteIdentifier","deleteNoteString","attr","moveNoteString","editNoteString","updateColumnAria","columnId","column","newNoteString","moveColumnString","deleteColumnString","each","index","stopNoteEdit","noteBorder","show","hide","remove","sortAfterDelete","columnID","sortorder","getColumn","children","filter","_","element","so","setAttachment","attachment","type","attType","val","decodeText","url","attachmentInfo","attachmentUrl","attachmentFile","prop","attachmentTypeToString","FileReader","attachmentTypeChanged","previewAttachment","filename","filecontents","encodeText","fileElem","elem","removeClass","addClass","blanktarget","videoID","match","undefined","getEmbedUrl","addNote","columnid","heading","content","owner","rating","ismynote","id","iseditable","pendingNote","notecontent","notecontrols","noteAuthorusername","noteAriaText","attachmentPreview","fullname","append","columnContent","beginEdit","showModalForm","startNoteEdit","rateElement","handleAction","result","canrate","rateRemoveText","hasrated","confirm","status","historyid","sortNotes","then","rateModal","getRoot","on","ModalEvents","hidden","rateNote","removeElement","deleteNote","moveElement","init","moveNote","editElement","updateSortable","fullScreenNote","lastOne","last","insertAfter","prepend","addColumn","name","locked","notes","colour","headerStyle","nameCache","columnHeader","columnSort","columnName","columnNewContent","hideheaders","lockIcon","lockElement","lockstring","str","lockColumn","moveColumn","getColumnName","callBeforeOnKeyEditing","is","Error","e","isAriaTriggerKey","keyCode","preventDefault","editable","handleEditableAction","toggleFontSize","closeOnEnter","newNoteButton","noteicon","timecreated","userid","columnSorting","selectHeadingColour","colCount","colourCount","colours","updateNote","processBoardHistory","ownerid","since","boardhistory","item","boardid","action","formModal","historyData","alert","forEach","detach","appendTo","instant","history_refresh","setTimeout","clearTimeout","toggle","desc","asc","sortCol","parent","direction","a","b","sortElements","sort","fromColumnID","sortable","connectWith","cancel","handle","start","ui","stop","tocolumn","this","noteid","payload","updateSortOrders","movingColumnId","axis","containment","toColumnID","noteID","newSortOrder","toColumn","movedNote","oldSortOrder","toChildren","sortOrder","fromChildren","getBody","params","Fragment","loadFragment","title","create","ModalFactory","types","SAVE_CANCEL","body","large","removeOnClose","modal","getBodyPromise","saveInProgress","setLarge","setSaveButtonText","setButtonText","save","submit","changeEvent","document","createEvent","initEvent","get","reportValidity","dispatchEvent","invalid","$","merge","first","focus","formData","stringify","serialize","jsonformdata","Y","use","M","core_formchangechecker","reset_form_dirty_state","destroy","mediaSelect","ytButton","pictureButton","linkButton","updateMediaButtons","addYoutube","addImage","addLink","postButton","cancelButton","modalRoot","button","getActionSelector","updateModalAria","catch","Notification","modalBody","createElement","clone","preview","commentArea","fetchFor","CANCEL","columns","newBusy","columnicon","stringsInfo","string","push","key","component","when","results","rawText","encodedText"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/board.js b/amd/src/board.js index 739f66c..cadbf16 100755 --- a/amd/src/board.js +++ b/amd/src/board.js @@ -1171,12 +1171,14 @@ export default function(settings) { var data = JSON.parse(item.content); if (item.action == 'add_note') { + // This is called on a board if someone else has added a note in a different browser. let sortorder = sortby == 3 ? data.sortorder : data.timecreated; addNote(data.columnid, data.id, data.heading, data.content, data.attachment, - {id: item.userid}, sortorder, data.rating); + {id: item.userid , fullname: item.userid + " " + item.fullname}, sortorder, data.rating); updateNoteAria(data.id); sortNotes($('.board_column[data-ident=' + data.columnid + '] .board_column_content')); } else if (item.action == 'update_note') { + // This is called on a board if someone else has updated a note in a different browser. let note = getNote(data.id), formModal = editModal, historyData = data; diff --git a/classes/board.php b/classes/board.php index 7976e90..3b4ae28 100644 --- a/classes/board.php +++ b/classes/board.php @@ -77,7 +77,7 @@ class board { /** @var int Value for the singleusermode setting in public mode*/ const SINGLEUSER_PUBLIC = 2; - static $alluserids = []; + static $alluserids = []; /** * Retrieves the course module for the board @@ -440,8 +440,20 @@ public static function board_history(int $boardid, int $ownerid, int $since): ar $params['ownerid'] = $ownerid; } } - - return $DB->get_records_select('board_history', $condition, $params); + $history_items = $DB->get_records_select('board_history', $condition, $params); + // Add fullname to each item in history if author should be displayed. + $config = get_config('mod_board'); + $allowshowauthorofnoteonboard = isset($config->allowshowauthorofnoteonboard) ? $config->allowshowauthorofnoteonboard : false; + if ($allowshowauthorofnoteonboard && self::board_show_authorofnote($board->id)) { + foreach ($history_items as $history_item) { + if (!self::$alluserids[$history_item->userid]) { + $user = core_user::get_user($history_item->userid); + self::$alluserids[$history_item->userid] = fullname($user); + } + $history_item->fullname =self::$alluserids[$history_item->userid]; + } + } + return $history_items; } /** diff --git a/external.php b/external.php index a2664fe..e7232fc 100755 --- a/external.php +++ b/external.php @@ -75,6 +75,7 @@ public static function board_history_returns(): external_multiple_structure { 'boardid' => new external_value(PARAM_INT, 'boardid'), 'action' => new external_value(PARAM_TEXT, 'action'), 'userid' => new external_value(PARAM_INT, 'userid'), + 'fullname' => new external_value(PARAM_TEXT, 'user fullname', VALUE_DEFAULT, ''), 'content' => new external_value(PARAM_RAW, 'content') ) )