canvas.js 131 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374
  1. /* Contains all the Javascript logic of the canvas and its main features: save, export and share */
  2. $(document).ready(function() {
  3. /* ================================================
  4. Miscellaneous
  5. ================================================= */
  6. // Prevent AJAX requests from being cached
  7. $.ajaxSetup({ cache: false });
  8. // Declare canvas id
  9. var canvasId = $("input[name='canvas_id']").val();
  10. // Declare canvas owner
  11. var canvasOwner;
  12. // Declare current user
  13. var username = $("input[name='username']").val();
  14. // Total number of collaborators
  15. var numberOfCollaborators = 0;
  16. // The user is a collaborator. If the user is not a collaborator, that means the canvas being viewed is public.
  17. var userIsCollaborator = false;
  18. // Initiate tag
  19. var tag = "";
  20. // Declare the currently loaded tags belonging to the user
  21. var tags = [];
  22. // Fixes bug when added item field zooms on tag click
  23. var tagWindowIsOpen = false;
  24. // The text area has been changed
  25. var textareaHasBeenChanged = false;
  26. // The idea ID for the current comments
  27. var currentCommentsId;
  28. // Prevent pressing ENTER on Project Title from submitting the form
  29. $('.proj_title').keydown(function(event){
  30. if(event.keyCode == 13) {
  31. event.preventDefault();
  32. return false;
  33. }
  34. });
  35. /* ================================================
  36. Remember whether the canvas is a new canvas or not
  37. ================================================= */
  38. // Declarations
  39. var canvasIsNew = true;
  40. // If canvasId is set. Whether the canvas is new or not is initially determined in the $_SESSION['canvas_id'] variable.
  41. if(canvasId) {
  42. // Remember that the canvas is not new
  43. canvasIsNew = false;
  44. }
  45. /* ================================================
  46. Remember if the user is a collaborator
  47. ================================================= */
  48. // If the canvas isn't new
  49. if(canvasIsNew === false) {
  50. // AJAX
  51. $.ajax({
  52. async: false,
  53. type: "POST",
  54. url: "php/check-is-collaborator.php",
  55. dataType: "TEXT",
  56. data: {
  57. "canvas_id": canvasId,
  58. "username": username
  59. },
  60. timeout: 5000,
  61. success: function(returnData) {
  62. // If the active user is a collaborator
  63. if(returnData === username) {
  64. userIsCollaborator = true;
  65. }
  66. },
  67. error: function(xhr) {
  68. console.log(xhr.statusText);
  69. }
  70. });
  71. }
  72. /* ================================================
  73. If the user is a collaborator or the canvas is new, show the items that aren't public
  74. ================================================= */
  75. // If the user is a collaborator or the canvas is new
  76. if(userIsCollaborator === true || canvasIsNew === true) {
  77. // If the user hovers over the canvas title
  78. $("input.proj_title").on("focusin mouseover", function() {
  79. // Change the cursor to a text cursor
  80. $(this).css("cursor", "text");
  81. });
  82. // If the user hovers over the tag description
  83. $("div#tag-window textarea#tag-description").on("focusin mouseover", function() {
  84. // Change the cursor to a text cursor
  85. $(this).css("cursor", "text");
  86. });
  87. // Show the Collaborators button
  88. $("div#collaborators-container").show();
  89. // Hide all buttons inside every category
  90. $("div.add_box").show();
  91. // Show the character count in the tag window
  92. $("div#tag-window p.chars-count").show();
  93. // Show the buttons in the tag window
  94. $("div#tag-window div#tag-buttons").show();
  95. // Show the message saying that the canvas is saved automatically
  96. $("div#saved-automatically").show();
  97. // Show the Publish This Canvas button
  98. $("button.publish_canvas").show();
  99. }
  100. /* ================================================
  101. If the user is using Try Online, show the Collaborators button
  102. ================================================= */
  103. // If the user isn't logged in
  104. if(username === "") {
  105. $("div#collaborators-container").show();
  106. $("div#collaborators-container").css("right", "50px");
  107. }
  108. /* ================================================
  109. Generate generic ID
  110. ================================================= */
  111. // Generate a random string of a specific length to be used as canvas_id
  112. function generateId() {
  113. var i = 0;
  114. var length = 10;
  115. var characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  116. var charactersLength = characters.length;
  117. var randomString = "";
  118. var minimum = 0;
  119. var maximum = charactersLength - 1;
  120. for (i = 0; i < length; i++) {
  121. randomString += characters[Math.floor(Math.random() * (maximum - minimum + 1)) + minimum];
  122. }
  123. return randomString;
  124. }
  125. /* ================================================
  126. Generate canvas ID
  127. ================================================= */
  128. // Generate canvas ID
  129. function generateCanvasId() {
  130. if(canvasId === "") {
  131. canvasId = generateId();
  132. $("input[name='canvas_id']").val(canvasId);
  133. }
  134. }
  135. // Generate canvas ID
  136. if(canvasId === "") {
  137. generateCanvasId();
  138. }
  139. /* ================================================
  140. Rearrange fields numerically if 1 column is displayed
  141. ================================================= */
  142. // Declarations
  143. var groupOneLayout = $("#7-5-col-layout");
  144. var groupTwoLayout = $("#2-col-layout");
  145. var groupThreeLayout = $("#1-col-layout");
  146. var field01 = $("#panel_01");
  147. var field03 = $("#panel_03");
  148. var field04 = $("#panel_04");
  149. var field09 = $("#panel_09");
  150. var field05 = $("#panel_05");
  151. var field06 = $("#panel_06");
  152. var field02 = $("#panel_02");
  153. var field07 = $("#panel_07");
  154. var field08 = $("#panel_08");
  155. var field10 = $("#panel_10");
  156. var isRearranged = false;
  157. // Rearrange the fields to suit mobile
  158. function rearrangeFields() {
  159. field01.detach();
  160. field03.detach();
  161. field04.detach();
  162. field09.detach();
  163. field05.detach();
  164. field06.detach();
  165. field02.detach();
  166. field07.detach();
  167. field08.detach();
  168. field10.detach();
  169. groupOneLayout.append(field01);
  170. groupOneLayout.append(field02);
  171. groupOneLayout.append(field03);
  172. groupOneLayout.append(field04);
  173. groupOneLayout.append(field05);
  174. groupOneLayout.append(field06);
  175. groupOneLayout.append(field07);
  176. groupOneLayout.append(field08);
  177. groupOneLayout.append(field09);
  178. groupOneLayout.append(field10);
  179. }
  180. // Rearrange the fields according to their original order
  181. function rearrangeFieldsOriginal() {
  182. field01.detach();
  183. field02.detach();
  184. field03.detach();
  185. field04.detach();
  186. field05.detach();
  187. field06.detach();
  188. field07.detach();
  189. field08.detach();
  190. field09.detach();
  191. field10.detach();
  192. groupOneLayout.append(field01);
  193. groupOneLayout.append(field03);
  194. groupOneLayout.append(field04);
  195. groupOneLayout.append(field09);
  196. groupOneLayout.append(field05);
  197. groupOneLayout.append(field06);
  198. groupOneLayout.append(field02);
  199. groupTwoLayout.append(field07);
  200. groupTwoLayout.append(field08);
  201. groupThreeLayout.append(field10);
  202. }
  203. // If the web page is opened on a mobile
  204. if($(window).width() <= 499) {
  205. rearrangeFields();
  206. }
  207. // When resizing the window
  208. $(window).on("resize", function() {
  209. // If the user is using a mobile device
  210. if(isRearranged === false && $(window).width() <= 499) {
  211. // Rearrange fields
  212. rearrangeFields();
  213. isRearranged = true;
  214. }
  215. // If the user is not using a mobil device
  216. else if(isRearranged === true && $(window).width() >= 500) {
  217. // Restore fields
  218. rearrangeFieldsOriginal();
  219. isRearranged = false;
  220. }
  221. });
  222. /* ================================================
  223. If the user changes the project title
  224. ================================================= */
  225. // If the user is a collaborator or the canvas is new
  226. if(userIsCollaborator === true || canvasIsNew === true) {
  227. // If the user focuses on the project title
  228. $("input.proj_title").unbind("focusin").on("focusin", function() {
  229. // Declarations
  230. var oldText = $(this).val();
  231. // If the user leaves the project title
  232. $("input.proj_title").unbind("focusout").on("focusout", function() {
  233. var newText = $(this).val();
  234. // If the project title has been changed
  235. if(newText !== oldText) {
  236. // Save the canvas
  237. prepareSaveCanvas();
  238. }
  239. });
  240. });
  241. }
  242. else {
  243. // If the user focuses on the project title
  244. $("input.proj_title").on("focusin", function(event) {
  245. // Blur immediately
  246. $(this).blur();
  247. });
  248. }
  249. /* ================================================
  250. Get the owner
  251. ================================================= */
  252. // Get the owner
  253. function getOwner() {
  254. // AJAX
  255. $.ajax({
  256. async: false,
  257. type: "POST",
  258. url: "php/get-owner.php",
  259. dataType: "TEXT",
  260. data: {
  261. "canvas_id": canvasId
  262. },
  263. timeout: 5000,
  264. success: function(returnData) {
  265. // Remember the canvas owner
  266. canvasOwner = returnData;
  267. },
  268. error: function(xhr) {
  269. console.log(xhr.statusText);
  270. }
  271. });
  272. }
  273. getOwner();
  274. /* ================================================
  275. Collaborators
  276. ================================================= */
  277. // Validate email
  278. function validateEmail(email) {
  279. var re = /\S+@\S+\.\S+/;
  280. return re.test(email);
  281. }
  282. // If the user clicks on the "Collaborators" button, show the collaborators window
  283. $("div#collaborators button").on("click", function() {
  284. // If the user is logged in
  285. if($("input[name='username']").val() != "") {
  286. // Show the collaborators window
  287. $("div#shadow").css("display", "block");
  288. $("div#collaborators-window").css("display", "block");
  289. // In 1.5 seconds
  290. window.setTimeout(function() {
  291. // If the canvas is new
  292. if(canvasIsNew === true) {
  293. // Save the canvas
  294. prepareSaveCanvas();
  295. }
  296. }, 1500);
  297. }
  298. // If the user isn't logged in
  299. else {
  300. // Show a dialog
  301. $("div#shadow").css("display", "block");
  302. $("div#dialog-log-in").css("display", "block");
  303. }
  304. });
  305. // Close the collaborators window
  306. function closeCollaboratorsWindow() {
  307. // Close the collaborators window
  308. $("div#shadow").css("display", "none");
  309. $("div#collaborators-window").css("display", "none");
  310. }
  311. // If the user clicks on the "Close" button in the Collaborators window
  312. $("div#collaborators-window > div.window-heading > button.close").on("click", function() {
  313. // Close the Collaborators window
  314. closeCollaboratorsWindow();
  315. $("div#collaborators-window div#collaborator-email").text("Please enter an email address...");
  316. $("div#user-is-not-member").hide();
  317. $("div#username-already-exists").hide();
  318. $("div#enter-valid-email").hide();
  319. });
  320. // If the user clicks on the "Close" button in the Remove Collaborator dialog
  321. $("div#dialog-remove-collaborator button.close").on("click", function() {
  322. // Close the Remove Collaborator window
  323. $("div#shadow").css("z-index", "2");
  324. $("div#dialog-remove-collaborator").css("display", "none");
  325. });
  326. // Remove the collaborator
  327. function removeCollaborator(collaborator, currentRow) {
  328. // AJAX
  329. $.ajax({
  330. timeout: 5000,
  331. dataType: "text",
  332. type: "post",
  333. data: {
  334. "canvas_id": canvasId,
  335. "collaborator": collaborator
  336. },
  337. url: "php/remove-collaborator.php",
  338. success: function() {
  339. // If the collaborator that has been removed is the active user
  340. if(collaborator === username) {
  341. // Redirect the user to the dashboard
  342. window.location.replace("php/dashboard.php");
  343. }
  344. // Close the Remove Collaborator window
  345. $("div#shadow").css("z-index", "2");
  346. $("div#dialog-remove-collaborator").css("display", "none");
  347. updateCollaboratorsView();
  348. // Update Collaborators
  349. updateCollaborators();
  350. },
  351. error: function(xhr) {
  352. console.log(xhr.statusText);
  353. }
  354. });
  355. }
  356. // If the user clicks on the "Remove" button
  357. function showRemoveCollaboratorDialog() {
  358. // If the user clicks on the "Remove" button
  359. $("div#collaborators-window td:nth-child(4) span").on("click", function() {
  360. // Declarations
  361. var collaborator = $(this).parent().prev().text();
  362. var currentRow = $(this).parent().parent();
  363. // Show the Remove Collaborator dialog
  364. $("div#shadow").css("z-index", "3");
  365. $("div#dialog-remove-collaborator").css("display", "block");
  366. // If the user clicks on "Yes"
  367. $("#dialog-remove-collaborator #button-yes").on("click", function() {
  368. // Remove the collaborator
  369. removeCollaborator(collaborator, currentRow);
  370. });
  371. // If the user clicks on "Cancel"
  372. $("#dialog-remove-collaborator #button-cancel").on("click", function() {
  373. // Cancel
  374. $("div#shadow").css("z-index", "2");
  375. $("div#dialog-remove-collaborator").css("display", "none");
  376. });
  377. });
  378. }
  379. // Show only active collaborators or show all
  380. function updateCollaboratorsView() {
  381. // If the user only wants to see active collaborators
  382. if($("input[name='show-only-active']").is(":checked")) {
  383. // For every collaborator
  384. $("div#collaborators-window tr").each(function() {
  385. // If the collaborator is offline
  386. if($(this).find("td:nth-child(1)").html() === "") {
  387. // Hide the collaborator
  388. $(this).css("display", "none");
  389. }
  390. });
  391. }
  392. // If the user wants to see all active collaborators
  393. else {
  394. // For every collaborator
  395. $("div#collaborators-window tr").each(function() {
  396. // Show the collaborator
  397. $(this).css("display", "table-row");
  398. });
  399. }
  400. }
  401. // If the user checks the "Show only active collaborators" checkbox
  402. $("input[name='show-only-active']").on("change", function() {
  403. // Show only active collaborators
  404. updateCollaboratorsView();
  405. });
  406. // If the user enters the email field
  407. $("div#collaborators-window div#collaborator-email").on("click", function() {
  408. // Focus on the email field
  409. $(this).focus();
  410. // If the text is the default text
  411. if($(this).text() === "Please enter an email address...") {
  412. $(this).text("");
  413. $(this).css("color", "rgb(51, 51, 51)");
  414. }
  415. });
  416. // If the user leaves the email field
  417. $("div#collaborators-window div#collaborator-email").on("focusout", function() {
  418. // If nothing has been entered
  419. if($(this).text() === "") {
  420. $(this).text("Please enter an email address...");
  421. $(this).css("color", "rgb(117, 117, 117)");
  422. }
  423. });
  424. // If the user leaves the email field or pastes text in it
  425. $("div#collaborators-window div#collaborator-email").on("paste", function(event) {
  426. // Replace HTML with plain text
  427. event.preventDefault();
  428. var text = (event.originalEvent || event).clipboardData.getData("text/plain");
  429. document.execCommand("insertText", false, text);
  430. });
  431. // If the user types a key inside the email field
  432. $("div#collaborators-window div#collaborator-email").on("keydown", function(event) {
  433. // If the user has pressed enter
  434. if(event.keyCode === 13) {
  435. event.preventDefault();
  436. }
  437. });
  438. // If the user clicks on "Add collaborator"
  439. $("div#collaborators-window button#add-collaborator").on("click", function() {
  440. // Declarations
  441. var collaborator = $("div#collaborators-window div#collaborator-email").text();
  442. // Reset error messages
  443. $("div#user-is-not-member").hide();
  444. $("div#username-already-exists").hide();
  445. $("div#enter-valid-email").hide();
  446. // If the email address is valid
  447. if(validateEmail(collaborator)) {
  448. // AJAX
  449. $.ajax({
  450. timeout: 5000,
  451. dataType: "text",
  452. type: "post",
  453. data: {
  454. "canvas_id": canvasId,
  455. "collaborator": collaborator
  456. },
  457. url: "php/add-collaborator.php",
  458. success: function(returnData) {
  459. // Hide error messages
  460. $("div#username-already-exists").hide();
  461. $("div#enter-valid-email").hide();
  462. // If the collaborator is not already a member
  463. if(returnData == 1) {
  464. $("div#user-is-not-member").show();
  465. numberOfCollaborators++;
  466. }
  467. // If the collaborator is already a collaborator
  468. else if(returnData == 2) {
  469. $("div#username-already-exists").show();
  470. numberOfCollaborators++;
  471. }
  472. // If everything is okay
  473. else if(returnData == 3) {
  474. // Restore the default text
  475. $("div#collaborators-window div#collaborator-email").text("Please enter an email address...");
  476. $("div#collaborators-window div#collaborator-email").css("color", "rgb(117, 117, 117)");
  477. // Update collaborators
  478. updateCollaborators();
  479. }
  480. },
  481. error: function(xhr) {
  482. console.log(xhr.statusText);
  483. }
  484. });
  485. }
  486. else {
  487. // Show an error message
  488. $("div#enter-valid-email").show();
  489. }
  490. });
  491. // Add the owner as a collaborator if the currently logged in user is the owner and hasn't been added before
  492. function addOwnerToCollaborators() {
  493. // AJAX
  494. $.ajax({
  495. async: false,
  496. type: "POST",
  497. url: "php/add-owner-to-collaborators.php",
  498. dataType: "TEXT",
  499. data: {
  500. "canvas_id": canvasId
  501. },
  502. timeout: 5000,
  503. error: function(xhr) {
  504. console.log(xhr.statusText);
  505. }
  506. });
  507. }
  508. // addOwnerToCollaborators();
  509. // Update collaborators
  510. function updateCollaborators() {
  511. // AJAX
  512. $.ajax({
  513. type: "POST",
  514. url: "php/update-collaborators.php",
  515. dataType: "JSON",
  516. data: {
  517. "canvas_id": canvasId,
  518. "username": username
  519. },
  520. timeout: 5000,
  521. success: function(returnData) {
  522. // Declarations
  523. var newHtml = "<tr><th>Active</th><th>Name</th><th>Username</th><th>Remove</th></tr>";
  524. var index = 0;
  525. // Remember the number of collaborators
  526. numberOfCollaborators = returnData.length;
  527. // While there still are collaborators to append
  528. while(index < returnData.length) {
  529. newHtml += "<tr><td class='collaborators-active'>";
  530. // If the collaborator is active
  531. if(returnData[index]["active"] === 1) {
  532. newHtml += "<span class='glyphicon glyphicon-ok-sign'></span>";
  533. }
  534. newHtml += "</td><td>" + returnData[index]["name"] + "</td><td>" + returnData[index]["collaborator"] + "</td><td>";
  535. // If the collaborator isn't the owner of the canvas
  536. if(returnData[index]["collaborator"] !== canvasOwner) {
  537. // Add the remove icon
  538. newHtml += "<span class='glyphicon glyphicon-remove-sign'></span>";
  539. }
  540. newHtml += "</td></tr>";
  541. // Increment the index
  542. index++;
  543. }
  544. // Append collaborators
  545. $("div#collaborators-window table").html(newHtml);
  546. // Update the button to open the collaborators window
  547. $("div#collaborators button span").text("Collaborators (" + $("td.collaborators-active span").length + " active)");
  548. // If the user clicks on the "Remove" button
  549. showRemoveCollaboratorDialog();
  550. // Show only active collaborators or show all
  551. updateCollaboratorsView();
  552. },
  553. error: function(xhr) {
  554. console.log(xhr.statusText);
  555. }
  556. });
  557. }
  558. // If the canvas is new
  559. if(canvasIsNew === false) {
  560. // Update the collaborators
  561. updateCollaborators();
  562. }
  563. // Post typing information
  564. function postTyping(typingId) {
  565. // AJAX
  566. $.ajax({
  567. type: "POST",
  568. url: "php/post-typing.php",
  569. dataType: "TEXT",
  570. data: {
  571. "canvas_id": canvasId,
  572. "username": username,
  573. "typing_id": typingId
  574. },
  575. timeout: 5000,
  576. error: function(xhr) {
  577. console.log(xhr.statusText);
  578. }
  579. });
  580. }
  581. // If the user closes the window
  582. $(window).on("beforeunload", function() {
  583. // Reset "User is typing" notification information
  584. postTyping("");
  585. });
  586. // Get typing information
  587. function getTyping() {
  588. // AJAX
  589. $.ajax({
  590. type: "POST",
  591. url: "php/get-typing.php",
  592. dataType: "JSON",
  593. data: {
  594. "canvas_id": canvasId,
  595. "username": username
  596. },
  597. timeout: 5000,
  598. success: function(returnData) {
  599. var loopCounter = 0;
  600. var typingDiv;
  601. var name;
  602. var typingId;
  603. var typingIds = [];
  604. // var typingDivIds = $("div.user-is-typing");
  605. // For every user user/DIV currently being typed in
  606. for(t in returnData) {
  607. name = returnData[loopCounter]["name"];
  608. typingId = returnData[loopCounter]["typingId"];
  609. // Save the typing ID in a separate array
  610. typingIds[loopCounter] = returnData[loopCounter]["typingId"];
  611. if($("#" + typingId + "-typing").length === 0) {
  612. typingDiv = "<div class='user-is-typing' id='" + typingId + "-typing'>" + name + "<br /> is typing...</div>";
  613. }
  614. // For the current idea
  615. $("#" + typingId).after(typingDiv);
  616. // Increment loop Counter
  617. loopCounter++;
  618. }
  619. // For every "user is typing" DIV on the canvas
  620. $("div.user-is-typing").each(function() {
  621. // If the typing ID of the current "user is typing" DIV does not exist in the new array with collaborators currently typing
  622. if($.inArray($(this).attr("id").substring(0, 10), typingIds) === -1) {
  623. // Remove this "user is typing" DIV
  624. $(this).remove();
  625. }
  626. });
  627. },
  628. error: function(xhr) {
  629. console.log(xhr.statusText);
  630. }
  631. });
  632. }
  633. // Get typing information every 1.5 seconds
  634. window.setInterval(function() {
  635. // If collaborators have been added
  636. if(numberOfCollaborators > 1) {
  637. // Get typing information
  638. getTyping();
  639. }
  640. }, 1500);
  641. /* ================================================
  642. "Jump to" functions
  643. ================================================= */
  644. // Declarations
  645. var hasScrolledDown = false;
  646. // If the user scrolls down, change "position" to "fixed"
  647. $(window).on("scroll", function() {
  648. // If the web page is opened on a mobile
  649. if($(window).width() <= 499) {
  650. // Declarations
  651. var scrollPosition = $(window).scrollTop();
  652. // If the user scrolls down
  653. if(hasScrolledDown === false && scrollPosition >= 200) {
  654. $("div.jump-to").show();
  655. $("div.jump-to-click-area").show();
  656. hasScrolledDown = true;
  657. }
  658. // If the user scrolls to the top
  659. else if(hasScrolledDown === true && scrollPosition <= 10) {
  660. $("div.jump-to").hide();
  661. $("div.jump-to-click-area").hide();
  662. hasScrolledDown = false;
  663. }
  664. }
  665. // If the web page is not opened on a mobile
  666. else {
  667. $("div.jump-to-click-area").show();
  668. $("div.jump-to").hide();
  669. hasScrolledDown = false;
  670. }
  671. });
  672. // If the user resizes the window
  673. $(window).on("resize", function(event){
  674. // If the web page is not opened on a mobile
  675. if($(this).width() >= 500) {
  676. // Restore the space between the header and Saved Tags
  677. $("div.jump-to-click-area").show();
  678. $("div.jump-to").hide();
  679. hasScrolledDown = false;
  680. }
  681. });
  682. // If the user clicks on "Jump to", show menu
  683. $("div.jump-to-click-area").on("click", function() {
  684. // Toggle the menu
  685. $("div.jump-to-list").slideToggle(300);
  686. // Rotate arrow
  687. $("img.jump-to-img").toggleClass("jump-to-arrow-90");
  688. $("img.jump-to-img").toggleClass("jump-to-arrow-0");
  689. return false;
  690. });
  691. // If the user clicks on a menu item
  692. $("div.jump-to ul a").on("click", function() {
  693. // Declarations
  694. var chosenLiIndex = $(this).parent().index();
  695. var chosenFieldPosition;
  696. var scrollPositionNew;
  697. // If the user has chosen the list item 0
  698. if(chosenLiIndex === 0) {
  699. // Detect the scroll position of the chosen field "Saved Tags"
  700. chosenFieldPosition = $("div.saved-tags").offset().top;
  701. }
  702. // If the user has chosen the list item 1-9
  703. else if(chosenLiIndex >= 1 && chosenLiIndex <= 9) {
  704. // Detect the scroll position of the chosen field
  705. chosenFieldPosition = $("div.field_0" + chosenLiIndex).offset().top;
  706. }
  707. // If the user has chosen the list item 10 or higher
  708. else {
  709. // Detect the scroll position of the chosen field
  710. chosenFieldPosition = $("div.field_" + chosenLiIndex).offset().top;
  711. }
  712. // If the user has scrolled down
  713. if(hasScrolledDown === true) {
  714. // Set the new scroll position
  715. scrollPositionNew = chosenFieldPosition - 58;
  716. // Toggle the menu
  717. $("div.jump-to-list").slideToggle(300);
  718. // Rotate arrow
  719. $("img.jump-to-img").toggleClass("jump-to-arrow-90");
  720. $("img.jump-to-img").toggleClass("jump-to-arrow-0");
  721. }
  722. // Apply the new scroll position
  723. $(window).scrollTop(scrollPositionNew);
  724. return false;
  725. });
  726. /* ================================================
  727. Show tooltip for every category
  728. ================================================= */
  729. // Activate the tooltips on hover
  730. $("a[data-toggle='tooltip']").tooltip({container: "body"});
  731. // If the user clicks on a tooltip
  732. $("a[data-toggle='tooltip']").on("click", function() {
  733. return false;
  734. });
  735. /* ================================================
  736. Remove all tags from all fields
  737. ================================================= */
  738. // Remove all tags from all fields
  739. function removeTags() {
  740. // AJAX
  741. $.ajax({
  742. type: "POST",
  743. url: "php/get-tags.php",
  744. dataType: "JSON",
  745. data: {
  746. "canvas_id": canvasId
  747. },
  748. timeout: 5000,
  749. success: function(returnData) {
  750. // Declarations
  751. var loopCounter = 0;
  752. // Remember the tags
  753. tags = returnData;
  754. // For every added item
  755. $("li.added_item .expandable").each(function() {
  756. // Replace HTML with plain text
  757. $(this).html($(this).text());
  758. });
  759. // If no tags have been added
  760. if(tags.length === 0) {
  761. // Reset default message
  762. $("div.saved-tags p").html("No tags could be found.");
  763. }
  764. },
  765. error: function(xhr) {
  766. console.log(xhr.statusText);
  767. }
  768. });
  769. }
  770. /* ================================================
  771. Get the tags from the database and apply them on the canvas
  772. ================================================= */
  773. // Apply tags
  774. function updateTags() {
  775. // Apply tags on the canvas
  776. window.setTimeout(function() {
  777. // Regular expressions
  778. RegExp.escape = function(s) {
  779. return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
  780. };
  781. // Sort tags by size
  782. tags.sort(function(a, b) {
  783. return b.length - a.length;
  784. });
  785. // Replace the tag
  786. function replace(currentIdea, textIn, textOut) {
  787. currentIdea.html(function() {
  788. return $(this).html().replace(textIn, textOut);
  789. });
  790. };
  791. // For every added item that currently isn't being edited
  792. $("li.added_item div.expandable").each(function() {
  793. // Declarations
  794. var currentIdea = $(this);
  795. var currentIdeaText = currentIdea.html();
  796. // For every tag
  797. for(var tag of tags) {
  798. // Replace the tag
  799. tag = RegExp.escape(tag);
  800. currentIdeaText = currentIdeaText.replace(new RegExp(tag, 'g'), '<span class="tag-with-badge-effect">' + tag + '</span>');
  801. }
  802. // Replace the HTML with plain text
  803. currentIdea.html(currentIdeaText);
  804. // For every tag badge
  805. currentIdea.find("span").each(function() {
  806. // Declarations
  807. var span = $(this);
  808. // If the parent is the current idea
  809. if(!span.parent().is(currentIdea)) {
  810. // Replace the span
  811. span.replaceWith(span.text());
  812. }
  813. });
  814. });
  815. // If the user hovers on a nested tag, only apply the badge effect on said tag
  816. $(".expandable span.tag-with-badge-effect").on("mouseover", function(event) {
  817. // Stop propagation
  818. event.stopPropagation();
  819. // Add the badge effect
  820. $(this).addClass("tag-with-badge-effect-hover");
  821. });
  822. // If the user leaves a tag, remove the badge effect
  823. $(".expandable span.tag-with-badge-effect").on("mouseout", function() {
  824. // Remove the badge effect
  825. $(this).removeClass("tag-with-badge-effect-hover");
  826. });
  827. // If the user clicks on a nested clack, stop propagation
  828. $(".expandable span.tag-with-badge-effect").on("click", function(event) {
  829. // Stop propagation
  830. event.stopPropagation();
  831. });
  832. // Show the tag window on tag click
  833. showTagWindowOnTagClick();
  834. }, 100);
  835. // Populate "Saved Tags"
  836. var loopCounter = 0;
  837. var savedTags = $("div.saved-tags p");
  838. // Sort tags alphabetically
  839. tags.sort(function(a, b) {
  840. if(a < b) return -1;
  841. if(a > b) return 1;
  842. return 0;
  843. });
  844. // Clear Saved Tags
  845. savedTags.html("");
  846. // For every tag
  847. for(t in tags) {
  848. // Append the tag in Saved Tags
  849. savedTags.append("<span class='tag-with-badge-effect'>" + tags[loopCounter] + "</span>").append("&nbsp;&nbsp; ");
  850. // Increment the index
  851. loopCounter++;
  852. }
  853. // If Saved Tags is empty
  854. if(savedTags.html() === "") {
  855. // Restore the default text
  856. savedTags.html("No tags could be found.");
  857. }
  858. }
  859. // Get the tags from the database
  860. function getTags() {
  861. // AJAX
  862. $.ajax({
  863. // async: false,
  864. type: "POST",
  865. url: "php/get-tags.php",
  866. dataType: "JSON",
  867. data: {
  868. "canvas_id": canvasId
  869. },
  870. timeout: 5000,
  871. success: function(returnData) {
  872. // Assign returnData to the tags variable
  873. tags = returnData;
  874. // Update tags on the canvas
  875. updateTags();
  876. },
  877. error: function(xhr) {
  878. console.log(xhr.statusText);
  879. }
  880. });
  881. }
  882. /* ================================================
  883. Tag window functions
  884. ================================================= */
  885. // Check if the tag is new
  886. function hideDeleteTagIfTagIsNew() {
  887. // Declarations
  888. var tagToAJAX = tag;
  889. // AJAX
  890. $.ajax({
  891. type: "POST",
  892. url: "php/check-if-tag-exists.php",
  893. dataType: "text",
  894. data: {
  895. "tag": tagToAJAX,
  896. "canvas_id": canvasId
  897. },
  898. timeout: 5000,
  899. success: function(returnData) {
  900. // If the current tag does not exist in the database
  901. if(returnData === "") {
  902. // Hide "Delete tag" button
  903. $("div#tag-window button#delete-tag").css("display", "none");
  904. }
  905. // If the current tag exists in the database
  906. else {
  907. // Show "Delete tag" button
  908. $("div#tag-window button#delete-tag").css("display", "inline");
  909. }
  910. },
  911. error: function(xhr) {
  912. console.log(xhr.statusText);
  913. }
  914. });
  915. }
  916. // Updating the remaining characters information
  917. function updateRemainingCharacters() {
  918. // Declarations
  919. var length = $("div#tag-window textarea#tag-description").val().length;
  920. var maxLength = 200;
  921. // Update length
  922. length = maxLength - length;
  923. // Show the remaining characters
  924. $("div#tag-window span.chars").text(length);
  925. }
  926. // Get the description for the selected tag
  927. function getDescriptionForSelectedTag() {
  928. // Declarations
  929. var tagToAJAX = tag;
  930. // AJAX
  931. $.ajax({
  932. type: "POST",
  933. url: "php/get-description-for-selected-tag.php",
  934. dataType: "text",
  935. data: {
  936. "tag": tagToAJAX,
  937. "canvas_id": canvasId
  938. },
  939. timeout: 5000,
  940. success: function(returnData) {
  941. // If the description isn't empty
  942. if(returnData != "") {
  943. // Update description field with the description for the selected tag
  944. $("div#tag-window textarea#tag-description").val(returnData);
  945. // Update remaining characters
  946. updateRemainingCharacters();
  947. }
  948. // If the description is empty
  949. else {
  950. // Restore default text
  951. $("div#tag-window textarea#tag-description").val("Please enter a description...");
  952. }
  953. textareaHasBeenChanged = true;
  954. },
  955. error: function(xhr) {
  956. console.log(xhr.statusText);
  957. }
  958. });
  959. }
  960. // Get similar tags by other users
  961. function getSimilarTags() {
  962. // Declarations
  963. var tagToAJAX = tag;
  964. // AJAX
  965. $.ajax({
  966. type: "POST",
  967. url: "php/get-similar-tags.php",
  968. dataType: "JSON",
  969. data: {
  970. "tag": tagToAJAX,
  971. "canvas_id": canvasId,
  972. "username": username
  973. },
  974. timeout: 5000,
  975. success: function(returnData) {
  976. // Reset similar tags if similar tags are to be showed again
  977. $("p.similar-tags-tag").remove();
  978. $("p.similar-tags-description").remove();
  979. $("p.similar-tags-canvas-name").remove();
  980. // Declarations
  981. var htmlToAppend = "";
  982. // If similar tags exist
  983. if(returnData.length > 0) {
  984. // Declarations
  985. var index = 0;
  986. // While there still are tags to append
  987. while(index < returnData.length) {
  988. htmlToAppend += "<p class='similar-tags-tag'><span class='tag-with-badge-effect'>" + returnData[index]["tag"] + "</span></p>"
  989. + "<p class='similar-tags-description'>" + returnData[index]["description"] + "</p>"
  990. + "<p class='similar-tags-canvas-name'>from <span class='canvas-name'>" + returnData[index]["canvas_name"] + "</span></p>";
  991. // Increment index
  992. index++;
  993. }
  994. // Append tags
  995. $("div#tag-window h2.similar-tags").after(htmlToAppend);
  996. $("p.similar-tags-description-none").css("display", "none");
  997. }
  998. else {
  999. // Show the message saying that there are no similar tags to show
  1000. $("p.similar-tags-description-none").css("display", "block");
  1001. }
  1002. },
  1003. error: function(xhr) {
  1004. console.log(xhr.statusText);
  1005. }
  1006. });
  1007. }
  1008. // Close the tag window
  1009. function closeTagWindow() {
  1010. // Close the tag window
  1011. tagWindowIsOpen = false;
  1012. // Update iew
  1013. $("div#shadow").css("display", "none");
  1014. $("div#tag-window").css("display", "none");
  1015. }
  1016. // If the user focuses on the tag description
  1017. $("div#tag-window textarea#tag-description").on("focusin", function(event) {
  1018. // If the user is not a collaborator
  1019. if(userIsCollaborator === false) {
  1020. // Focus out of the tag description
  1021. $(this).blur();
  1022. }
  1023. });
  1024. // Show the tag window
  1025. function showTagWindow() {
  1026. // Show the tag window
  1027. $("div#shadow").css("display", "block");
  1028. $("div#tag-window").css("display", "block");
  1029. // Update the header
  1030. $("div#tag-window h1").html("<span class='glyphicon glyphicon-tag'></span> " + tag);
  1031. // Check if the tag is new
  1032. hideDeleteTagIfTagIsNew();
  1033. // Get the description for the selected tag
  1034. getDescriptionForSelectedTag();
  1035. // Get tags by other users from the database
  1036. getSimilarTags();
  1037. // Update remaining characters in case description is loaded
  1038. updateRemainingCharacters();
  1039. // If a description hasn't been entered
  1040. if($("div#tag-window textarea#tag-description") !== "Please enter a description..." && textareaHasBeenChanged !== true) {
  1041. // Reset the remaining characters information
  1042. $("div#tag-window span.chars").text("200");
  1043. }
  1044. }
  1045. // If the user presses a key in the description textarea
  1046. $("div#tag-window textarea#tag-description").on("keyup", function() {
  1047. // Update remaining characters
  1048. updateRemainingCharacters();
  1049. });
  1050. // If the user clicks on the "Save tag" button
  1051. $("div#tag-window #save-tag").on("click", function() {
  1052. // Declarations
  1053. var description = $("div#tag-window textarea#tag-description").val();
  1054. var tagToAJAX = tag;
  1055. // If a description has been entered
  1056. if(description != "" && description != "Please enter a description...") {
  1057. // AJAX
  1058. $.ajax({
  1059. timeout: 5000,
  1060. dataType: "text",
  1061. type: "post",
  1062. data: {
  1063. "tag": tagToAJAX,
  1064. "description": description,
  1065. "canvas_id": canvasId
  1066. },
  1067. url: "php/save-tag.php",
  1068. success: function() {
  1069. textareaHasBeenChanged = true;
  1070. // Get the tags from the database and apply them on the canvas
  1071. getTags();
  1072. },
  1073. error: function(xhr) {
  1074. console.log(xhr.statusText);
  1075. }
  1076. });
  1077. // Close the tag window
  1078. closeTagWindow();
  1079. }
  1080. });
  1081. // If the user clicks on the "Close" button
  1082. $("div#tag-window button.close").on("click", function() {
  1083. // Close the tag window
  1084. closeTagWindow();
  1085. });
  1086. // If the user clicks on the "Delete tag" button
  1087. $("div#tag-window #delete-tag").on("click", function() {
  1088. // Declarations
  1089. var tagToAJAX = tag;
  1090. // AJAX
  1091. $.ajax({
  1092. timeout: 5000,
  1093. dataType: "text",
  1094. type: "post",
  1095. data: {
  1096. "tag": tagToAJAX,
  1097. "canvas_id": canvasId
  1098. },
  1099. url: "php/delete-tag.php",
  1100. success: function() {
  1101. // Remove all tags from all fields
  1102. removeTags();
  1103. // Get the tags from the database and apply them on the canvas
  1104. getTags();
  1105. },
  1106. error: function(xhr) {
  1107. console.log(xhr.statusText);
  1108. }
  1109. });
  1110. // Close the tag window
  1111. closeTagWindow();
  1112. });
  1113. // If the user focuses in the textarea
  1114. $("div#tag-window textarea#tag-description").on("focusin", function() {
  1115. // Declarations
  1116. var description = $("div#tag-window textarea#tag-description").val();
  1117. // If a description hasn't been entered
  1118. if(description === "Please enter a description...") {
  1119. // Empty the description textarea
  1120. $("div#tag-window textarea#tag-description").val("");
  1121. }
  1122. });
  1123. // If the user leaves the textarea
  1124. $("div#tag-window textarea#tag-description").on("focusout", function() {
  1125. // Declarations
  1126. var description = $("div#tag-window textarea#tag-description").val();
  1127. // If a description hasn't been entered
  1128. if(description === "") {
  1129. // Reset the description textarea
  1130. $("div#tag-window textarea#tag-description").val("Please enter a description...");
  1131. }
  1132. });
  1133. /* ================================================
  1134. If the user clicks on a tag, show the tag window
  1135. ================================================= */
  1136. // If the user clicks on a tag
  1137. function showTagWindowOnTagClick() {
  1138. $("span.tag-with-badge-effect").on("click", function() {
  1139. // If the user is logged in
  1140. if($("input[name='username']").val() != "") {
  1141. // Declarations
  1142. tag = $(this).text();
  1143. // Remember that the tag window is open
  1144. tagWindowIsOpen = true;
  1145. // Show the tag window
  1146. showTagWindow();
  1147. }
  1148. // If the user isn't logged in
  1149. else {
  1150. // Show a dialog
  1151. $("div#shadow").css("display", "block");
  1152. $("div#dialog-log-in").css("display", "block");
  1153. }
  1154. });
  1155. }
  1156. /* ================================================
  1157. Save added idea on Enter press
  1158. ================================================= */
  1159. // Save added idea on Enter press
  1160. function saveAddedIdeaOnEnterPress(li) {
  1161. // If the user presses a key
  1162. $("li.added_item textarea.expandable").unbind("keydown").on("keydown", function(event) {
  1163. // If the key is Enter
  1164. if(event.which === 13) {
  1165. // Prevent default behaviour
  1166. event.preventDefault();
  1167. // Declarations
  1168. var li = $(this).parent();
  1169. var textElement;
  1170. var textElementId = $(this).attr("id");
  1171. var textElementWidth;
  1172. var oldText = $(this).text();
  1173. // Replace textarea with a div
  1174. $(this).replaceWith(
  1175. "<div class='expandable' id='" + textElementId + "' name='" + $(this).attr("name") + "'>" + $(this).val() + "</div>"
  1176. );
  1177. // Reset "User is typing" notification information
  1178. if(numberOfCollaborators > 1) {
  1179. // Post typing information
  1180. postTyping("");
  1181. }
  1182. // Remember the text element
  1183. textElement = li.find(".expandable");
  1184. // Remember the width of the text element
  1185. textElementWidth = textElement.width();
  1186. // Change the cursor
  1187. $("ul.item_list div.expandable").css("cursor", "pointer");
  1188. // Update tags on the canvas
  1189. getTags();
  1190. // Zoom out animation
  1191. if(textElementWidth >= 0 && textElementWidth <= 250) {
  1192. textElement.addClass("zoom-out-regular");
  1193. }
  1194. else if(textElementWidth >= 251 && textElementWidth <= 500) {
  1195. textElement.addClass("zoom-out-less");
  1196. }
  1197. else if(textElementWidth >= 501) {
  1198. textElement.addClass("zoom-out-least");
  1199. }
  1200. textElement.css("background-color", "rgba(255, 255, 255, 0.75)");
  1201. textElement.css("-ms-transform", "scale(1)");
  1202. textElement.css("-webkit-transform", "scale(1)");
  1203. textElement.css("transform", "scale(1)");
  1204. // If no tags have been added
  1205. if(tags.length === 0) {
  1206. // Reset the text explaining that no tags have been added
  1207. $("div.saved-tags p").html("No tags could be found.");
  1208. }
  1209. // Save the canvas automatically if the user has logged in
  1210. var newText = textElement.text();
  1211. // If the text has been changed
  1212. if(oldText !== newText) {
  1213. // Save the canvas
  1214. prepareSaveCanvas();
  1215. }
  1216. // Toggle the text element on focus
  1217. toggleTextElementOnFocus();
  1218. }
  1219. });
  1220. }
  1221. /* ================================================
  1222. Toggle textarea.expandable/div.expandable on edit
  1223. ================================================= */
  1224. // Toggle the HTML element of the idea on focus
  1225. function toggleTextElementOnFocus() {
  1226. // If the user clicks on an added idea
  1227. $("li.added_item .expandable").unbind("click").on("click", function(event) {
  1228. // If the tag window isn't open
  1229. if(tagWindowIsOpen === false) {
  1230. var li = $(this).parent();
  1231. var textElement;
  1232. var textElementId = $(this).attr("id");
  1233. var textElementWidth;
  1234. var oldText = $(this).text();
  1235. // Replace div with a textarea
  1236. $(this).replaceWith(
  1237. "<textarea maxlength='100' class='expandable' id='" + textElementId + "' rows='3' data-limit-rows='true' data-autoresize name='" + $(this).attr("name") + "'>" + $(this).text() + "</textarea>"
  1238. );
  1239. // If collaborators have been added
  1240. if(numberOfCollaborators > 1) {
  1241. // Notify collaborators that the user is currently typing
  1242. postTyping(textElementId);
  1243. }
  1244. // Remember the text element
  1245. textElement = li.find(".expandable");
  1246. // Remember the width of the text element
  1247. textElementWidth = textElement.width();
  1248. // Focus immediately on click instead of having to click on the element a second time
  1249. textElement.focus();
  1250. // Zoom in animation
  1251. if(textElementWidth >= 0 && textElementWidth <= 250) {
  1252. textElement.addClass("zoom-in-regular");
  1253. textElement.css("background-color", "rgba(255, 255, 255, 1)");
  1254. textElement.css("-ms-transform", "scale(1.02)");
  1255. textElement.css("-webkit-transform", "scale(1.02)");
  1256. textElement.css("transform", "scale(1.02)");
  1257. }
  1258. else if(textElementWidth >= 251 && textElementWidth <= 600) {
  1259. textElement.addClass("zoom-in-less");
  1260. textElement.css("background-color", "rgba(255, 255, 255, 1)");
  1261. textElement.css("-ms-transform", "scale(1.01)");
  1262. textElement.css("-webkit-transform", "scale(1.01)");
  1263. textElement.css("transform", "scale(1.01)");
  1264. }
  1265. else if(textElementWidth >= 601) {
  1266. textElement.addClass("zoom-in-least");
  1267. textElement.css("background-color", "rgba(255, 255, 255, 1)");
  1268. textElement.css("-ms-transform", "scale(1.005)");
  1269. textElement.css("-webkit-transform", "scale(1.005)");
  1270. textElement.css("transform", "scale(1.005)");
  1271. }
  1272. // Save added idea on Enter press
  1273. saveAddedIdeaOnEnterPress(li);
  1274. // Replace textarea with a div
  1275. $("li.added_item textarea.expandable").unbind("focusout").on("focusout", function(event) {
  1276. // Declarations
  1277. var li = $(this).parent();
  1278. var textElement;
  1279. var textElementId = $(this).attr("id");
  1280. var textElementWidth;
  1281. // Replace textarea with a div
  1282. $(this).replaceWith(
  1283. "<div class='expandable' id='" + textElementId + "' name='" + $(this).attr("name") + "'>" + $(this).val() + "</div>"
  1284. );
  1285. // Reset "User is typing" notification information
  1286. if(numberOfCollaborators > 1) {
  1287. // Post typing information
  1288. postTyping("");
  1289. }
  1290. // Remember the text element
  1291. textElement = li.find(".expandable");
  1292. // Remember the width of the text element
  1293. textElementWidth = textElement.width();
  1294. // Change the cursor
  1295. $("ul.item_list div.expandable").css("cursor", "pointer");
  1296. // Update tags on the canvas
  1297. getTags();
  1298. // Zoom out animation
  1299. if(textElementWidth >= 0 && textElementWidth <= 250) {
  1300. textElement.addClass("zoom-out-regular");
  1301. }
  1302. else if(textElementWidth >= 251 && textElementWidth <= 500) {
  1303. textElement.addClass("zoom-out-less");
  1304. }
  1305. else if(textElementWidth >= 501) {
  1306. textElement.addClass("zoom-out-least");
  1307. }
  1308. textElement.css("background-color", "rgba(255, 255, 255, 0.75)");
  1309. textElement.css("-ms-transform", "scale(1)");
  1310. textElement.css("-webkit-transform", "scale(1)");
  1311. textElement.css("transform", "scale(1)");
  1312. // If no tags have been added
  1313. if(tags.length === 0) {
  1314. // Reset the text explaining that no tags have been added
  1315. $("div.saved-tags p").html("No tags could be found.");
  1316. }
  1317. // Save the canvas automatically if the user has logged in
  1318. var newText = textElement.text();
  1319. // If the text has been changed
  1320. if(oldText !== newText) {
  1321. // Save the canvas
  1322. prepareSaveCanvas();
  1323. }
  1324. // Toggle the text element on focus
  1325. toggleTextElementOnFocus();
  1326. });
  1327. }
  1328. });
  1329. }
  1330. /* ----------------------------------------------
  1331. Limiting the number of characters the user is allowed to type
  1332. ----------------------------------------------- */
  1333. // Declarations
  1334. var maxLength = 100;
  1335. $('.card').on('keyup', '.new_item', function() {
  1336. var length = $(this).val().length;
  1337. length = maxLength - length;
  1338. // Show the characters remaining only on this field
  1339. $(this).closest('.user-input').find('.chars').text(length);
  1340. });
  1341. function limitLengthOnInput() {
  1342. // Limit text on key press
  1343. $("li.added_item .expandable").unbind("keypress").on("keypress", function(event) {
  1344. // Declarations
  1345. var numberOfTags = $(this).children().filter("a").length;
  1346. var textLength = $(this).html().length;
  1347. // Subtract 43 from textLength per tag (the tag HTML is 43 characters)
  1348. $(this).each(function() {
  1349. textLength -= 43 * numberOfTags;
  1350. });
  1351. if(textLength === 100) { // Windows menu/Right cmd
  1352. event.preventDefault();
  1353. }
  1354. });
  1355. }
  1356. /* ================================================
  1357. If the user closes a dialog
  1358. ================================================= */
  1359. // If the user clicks on a close button inside a dialog
  1360. $("div.dialog").not($("div.window-dialog")).find("button.close").on("click", function() {
  1361. // Close the dialog
  1362. $("div#shadow").css("display", "none");
  1363. $("div.dialog").css("display", "none");
  1364. });
  1365. /* ================================================
  1366. If the user clicks on the "Tag selected term" link
  1367. ================================================= */
  1368. // Declarations
  1369. var selection = "";
  1370. // If the user selects new text
  1371. document.onselectionchange = function() {
  1372. // If the user has focused on an idea
  1373. if($("li.added_item .expandable").is(":focus")) {
  1374. // Update the tag variable
  1375. selection = window.getSelection().toString();
  1376. tag = selection.trim();
  1377. }
  1378. }
  1379. // If the user clicks on the "Tag selected term" link
  1380. $("p.tag-selected-term a").on("click", function() {
  1381. // If the user is not logged in
  1382. if($("input[name='username']").val() === "") {
  1383. // Show a dialog
  1384. $("div#shadow").css("display", "block");
  1385. $("div#dialog-log-in").css("display", "block");
  1386. }
  1387. // If the tag isn't empty
  1388. else if(canvasIsNew === true) {
  1389. // Show a dialog
  1390. $("div#shadow").css("display", "block");
  1391. $("div#dialog-please-save").css("display", "block");
  1392. }
  1393. // If no term has been selected
  1394. else if(tag === "") {
  1395. // Show a dialog
  1396. $("div#shadow").css("display", "block");
  1397. $("div#dialog-select-term").css("display", "block");
  1398. }
  1399. // If a term has been selected
  1400. else if(tag != "") {
  1401. // Show the tag window
  1402. showTagWindow();
  1403. }
  1404. // Prevent the current view to jump to the top of the screen
  1405. return false;
  1406. });
  1407. // If the user leaves the idea
  1408. $("li.added_item .expandable").on("focusout", function() {
  1409. // Reset variables
  1410. selection = "";
  1411. tag = "";
  1412. });
  1413. /* ================================================
  1414. Serialize Form to JSON
  1415. ================================================= */
  1416. // Serialize Form to JSON
  1417. $.fn.serializeObject = function() {
  1418. // Declarations
  1419. var o = {};
  1420. var a = this.serializeArray();
  1421. var addedIdeaLists = $(".card ul");
  1422. $.each(a, function() {
  1423. if(o[this.name]) {
  1424. if(!o[this.name].push) {
  1425. o[this.name] = [o[this.name]];
  1426. }
  1427. o[this.name].push(this.value || '');
  1428. }
  1429. else {
  1430. o[this.name] = this.value || '';
  1431. }
  1432. });
  1433. // Add added ideas to the JSON object manually
  1434. $.each(addedIdeaLists, function() {
  1435. // Declarations
  1436. var field = $(this).attr("id");
  1437. var addedItemDivs = $(this).find($(".expandable"));
  1438. var addedItemArray = [];
  1439. var numberOfAddedItem = addedItemDivs.length;
  1440. // For every idea
  1441. for(var i = 0; i < numberOfAddedItem; i++) {
  1442. addedItemArray[i] = [addedItemDivs[i].textContent, addedItemDivs[i].id];
  1443. }
  1444. // Add the idea to the array
  1445. o[field + "[]"] = addedItemArray;
  1446. });
  1447. return o;
  1448. };
  1449. /* ================================================
  1450. Getting the current date
  1451. ================================================= */
  1452. // Declarations
  1453. var fullDate = new Date();
  1454. var fourDigitYear = fullDate.getFullYear();
  1455. var twoDigitMonth = fullDate.getMonth() + 1 + "";
  1456. var twoDigitDate = fullDate.getDate() + "";
  1457. var currentDate;
  1458. // If the month digit is 1 character long
  1459. if(twoDigitMonth.length == 1) {
  1460. // Add the prefix "0"
  1461. twoDigitMonth = "0" + twoDigitMonth;
  1462. }
  1463. // If the date digit is 1 character long
  1464. if(twoDigitDate.length == 1) {
  1465. // Add the prefix "0"
  1466. twoDigitDate = "0" + twoDigitDate;
  1467. }
  1468. // Save the current date
  1469. currentDate = fourDigitYear + "-" + twoDigitMonth + "-" + twoDigitDate;
  1470. // Set the current date in the date input field
  1471. $(".proj_date").val(currentDate);
  1472. /* ================================================
  1473. If the user clicks on "Log Out"
  1474. ================================================= */
  1475. // If the user clicks on "Log Out"
  1476. $('#user-profile').on('click', '#logout', function() {
  1477. var url = "php/logout.php";
  1478. $.post(url, function(data, status) {
  1479. if(data == 200) {
  1480. $("#user-profile").hide();
  1481. $(".invited-members").hide();
  1482. window.location.href = "https://www.ethicscanvas.org";
  1483. }
  1484. });
  1485. });
  1486. /* ================================================
  1487. Check if the canvas is public
  1488. ================================================= */
  1489. // Check if the canvas is public
  1490. function checkPublic() {
  1491. // AJAX
  1492. $.ajax({
  1493. type: "POST",
  1494. url: "php/check-public.php",
  1495. dataType: "TEXT",
  1496. data: {
  1497. "canvas_id": canvasId
  1498. },
  1499. timeout: 5000,
  1500. success: function(returnData) {
  1501. if(returnData === "0") {
  1502. $("button.publish_canvas").text("Publish for viewing/commenting");
  1503. }
  1504. else if(returnData === "1") {
  1505. $("button.publish_canvas").text("Unpublish for viewing/commenting");
  1506. }
  1507. },
  1508. error: function(xhr) {
  1509. console.log(xhr.statusText);
  1510. }
  1511. });
  1512. }
  1513. /* ================================================
  1514. When the page loads, import the chosen canvas if the user has
  1515. picked one from the dashboard, otherwise load an empty canvas
  1516. ================================================= */
  1517. // Import the canvas from the server
  1518. function importCanvasFirst() {
  1519. // If a canvas is chosen by the user to be loaded
  1520. if(current_canvas_id !== '') {
  1521. var url = 'json/' + current_canvas_id + '.json';
  1522. // var url= 'json/test_canvas.json';
  1523. // Get the saved JSON object in the sendJSON.text file
  1524. $.getJSON(url, function(returnedObj) {
  1525. // Display the JSON data in the HTML
  1526. var itemListHTML = '';
  1527. // Iterate through the object
  1528. $.each(returnedObj, function(key, value) {
  1529. // Project name and item field
  1530. if(key === 'field_00[]') {
  1531. $('.form-header').find('input.proj_title').val(value[0]);
  1532. $('.form-header').find('input.proj_date').val(value[1]);
  1533. }
  1534. else if(key !== 'new_item') {
  1535. // An array
  1536. if($.type(value) === "array") {
  1537. $.each(value, function(i, itm) {
  1538. // FIX DUPLICATIONS in the canvas when importing. Importing will override the canvas content clear the canvas by giving en empty content to the ul list (remove previous list items)
  1539. $('.canvas-form').find('.card').filter('.' + key.substr(0, 8)).find('ul.item_list').html('');
  1540. // Create a list item with each value item and give it text area with the name attribute as the "key" (right field name)
  1541. itemListHTML +=
  1542. '<li class="added_item"><div class="expandable" id="' + itm[1] + '" name="' + key + '">' + itm[0] + '</div><br /><span class="comment glyphicon glyphicon-public glyphicon-comment"></span><span class="handle glyphicon glyphicon-list"></span><span class="move-up glyphicon glyphicon-chevron-up"></span><span class="move-down glyphicon glyphicon-chevron-down"></span><span class="remove glyphicon glyphicon-remove-circle"></span></li>';
  1543. });
  1544. }
  1545. // A single value string
  1546. else {
  1547. itemListHTML +=
  1548. '<li class="added_item"><div class="expandable" name="' + key + '">' + value + '</div><br /><span class="comment glyphicon glyphicon-public glyphicon-comment"></span><span class="handle glyphicon glyphicon-list"></span><span class="move-up glyphicon glyphicon-chevron-up"></span><span class="move-down glyphicon glyphicon-chevron-down"></span><span class="remove glyphicon glyphicon-remove-circle"></span></li>';
  1549. }
  1550. // Append the created list items/textatreas to the right field based on the "key"*/
  1551. // The str.substr(start,length) is used to remove the [] from the end of the "key"name (for each field. also the name attributes accociated with each fields) so that we can select the right class (right field) and append the created lists to the right field so field names/key/name attribute will tuen into class names: ex: field_1[] becomes field_1
  1552. // Find the field by its class names besed on the current key name
  1553. // Append the created list of item values to that right field
  1554. $('.canvas-form').find('.card').filter('.' + key.substr(0, 8)).find('ul.item_list').append(itemListHTML);
  1555. // $('form').find('.card').filter('.field_1').find('ul.item_list').append(itemListHTML);
  1556. // !! Empty the item list after each count of "key" so that the previous item lists from the other fields (associated with the previous key) don't get added up to the item list of other fields
  1557. itemListHTML = '';
  1558. // Limit the text in the idea field if it reaches the max length
  1559. limitLengthOnInput();
  1560. // If the user is a collaborator
  1561. if(userIsCollaborator === true) {
  1562. // Show the idea buttons
  1563. $("ul.item_list span.glyphicon").show();
  1564. // Change the cursor
  1565. $("ul.item_list div.expandable").css("cursor", "pointer");
  1566. // Toggle textarea.expandable/div.expandable on focus
  1567. toggleTextElementOnFocus();
  1568. // Show "Tag selected term" link
  1569. // For every list of ideas
  1570. $(".card .item_list").each(function() {
  1571. // the list of ideas has ideas
  1572. if($(this).find("li.added_item").length) {
  1573. // Show "Tag selected term"
  1574. $(this).next().show();
  1575. }
  1576. });
  1577. }
  1578. // Get typing information
  1579. getTyping();
  1580. // Get owner
  1581. getOwner();
  1582. // Show the owner of the canvas in the Collaborators window
  1583. $("p#canvas-owner").text(canvasOwner);
  1584. // Get the tags from the database and apply them on the canvas
  1585. getTags();
  1586. // Remember that the canvas isn't new
  1587. canvasIsNew = false;
  1588. // Check if the canvas is public
  1589. checkPublic();
  1590. }
  1591. });
  1592. });
  1593. }
  1594. }
  1595. importCanvasFirst();
  1596. /* ================================================
  1597. Receiving remote updates from collaborators
  1598. ================================================= */
  1599. // Import the canvas from the server
  1600. function importCanvasAgain() {
  1601. // If a canvas is chosen by the user to be loaded
  1602. if(current_canvas_id !== '') {
  1603. var url = 'json/' + current_canvas_id + '.json';
  1604. // var url= 'json/test_canvas.json';
  1605. // Get the saved JSON object in the sendJSON.text file
  1606. $.getJSON(url, function(returnedObj) {
  1607. // Display the JSON data in the HTML
  1608. var itemListHTML = '';
  1609. var ideaIdsJSON = [];
  1610. // Iterate through the object
  1611. $.each(returnedObj, function(key, value) {
  1612. // Project name and item field
  1613. if(key === 'field_00[]') {
  1614. // If the current Project Title has a different text from the text in the JSON file
  1615. if($('.form-header').find('input.proj_title').val() !== value[0]) {
  1616. // If the Project Title isn't currently being edited
  1617. if(!$('.form-header').find('input.proj_title').is(":focus")) {
  1618. $('.form-header').find('input.proj_title').val(value[0]);
  1619. }
  1620. }
  1621. $('.form-header').find('input.proj_date').val(value[1]);
  1622. }
  1623. else if(key !== 'new_item') {
  1624. // An array
  1625. if($.type(value) === "array") {
  1626. $.each(value, function(i, itm) {
  1627. // Declarations
  1628. var ideaTextJSON = itm[0];
  1629. var ideaIdJSON = itm[1];
  1630. // Add the current idea ID to the array
  1631. ideaIdsJSON.push(ideaIdJSON);
  1632. // console.log("We are now about to check if the idea \"" + $("#" + ideaIdJSON) + "\" exists on the currently viewed canvas");
  1633. // If the idea exists in the JSON file and on the currently viewed canvas (then the idea might or might not have been changed)
  1634. if($("#" + ideaIdJSON).length > 0) {
  1635. // console.log("The idea \"" + ideaIdJSON + "\" exists in both the JSON file and on the currently viewed canvas");
  1636. // console.log("We are now about to compare \"" + $("#" + ideaIdJSON).text() + "\" with \"" + ideaTextJSON + "\"");
  1637. // If the current idea has a different text from the text in the JSON file
  1638. if($("#" + ideaIdJSON).text() !== ideaTextJSON) {
  1639. // console.log("The text of \"" + ideaIdJSON + "\" has been changed by either you or a collaborator");
  1640. // If the current idea isn't currently being edited
  1641. if($("#" + ideaIdJSON).prop("tagName") === "DIV") {
  1642. // console.log("The current idea is a DIV");
  1643. // Update the current idea with the text in the JSON file
  1644. $("#" + ideaIdJSON).text(ideaTextJSON);
  1645. // Add Notification effect
  1646. // $("#" + ideaIdJSON).css("-webkit-animation-name", "update-notification");
  1647. // $("#" + ideaIdJSON).css("-webkit-animation-duration", "2s");
  1648. $("#" + ideaIdJSON).css("animation-name", "update-notification");
  1649. $("#" + ideaIdJSON).css("animation-duration", "2s");
  1650. // Remove Notification effect
  1651. window.setTimeout(function() {
  1652. // $("#" + ideaIdJSON).css("-webkit-animation-name", "");
  1653. // $("#" + ideaIdJSON).css("-webkit-animation-duration", "");
  1654. $("#" + ideaIdJSON).css("animation-name", "");
  1655. $("#" + ideaIdJSON).css("animation-duration", "");
  1656. }, 2000);
  1657. }
  1658. }
  1659. }
  1660. // If the idea exists in either the JSON file or on the currently viewed canvas, but not both
  1661. else {
  1662. // console.log("The idea exists in either the JSON file or on the currently viewed canvas, but not both");
  1663. // If the idea exists in the JSON file, but not on the currently viewed canvas (then the idea is new)
  1664. if(ideaIdJSON) {
  1665. // console.log("The idea \"" + ideaIdJSON + "\" is new");
  1666. // Create the idea
  1667. itemListHTML +=
  1668. '<li class="added_item"><div class="expandable" id="' + ideaIdJSON + '" name="' + key + '">' + ideaTextJSON + '</div><br /><span class="comment glyphicon glyphicon-public glyphicon-comment"></span><span class="handle glyphicon glyphicon-list"></span><span class="move-up glyphicon glyphicon-chevron-up"></span><span class="move-down glyphicon glyphicon-chevron-down"></span><span class="remove glyphicon glyphicon-remove-circle"></span></li>';
  1669. // Append the idea to the item list
  1670. $('.canvas-form').find('.card').filter('.' + key.substr(0, 8)).find('ul.item_list').append(itemListHTML);
  1671. }
  1672. }
  1673. });
  1674. }
  1675. }
  1676. });
  1677. // If the idea doesn't exist in the JSON file, but on the currently viewed canvas (then the idea has been removed)
  1678. // Declarations
  1679. var ideasCanvas = $(".added_item .expandable");
  1680. // For every idea on the currently viewed canvas
  1681. for(var counter = 0; counter < ideasCanvas.length; counter++) {
  1682. // Declarations
  1683. var ideaIdCanvas = ideasCanvas[counter].id;
  1684. // If the current idea on the currently viewed canvas doesn't exist in the JSON file
  1685. if(ideaIdsJSON.indexOf(ideaIdCanvas) === -1) {
  1686. // If there are no ideas left
  1687. if($("#" + ideaIdCanvas).parent().parent().length === 1) {
  1688. // Hide "Tag selected term" link
  1689. $("#" + ideaIdCanvas).parent().parent().next().css("display", "none");
  1690. }
  1691. // Delete the idea
  1692. $("#" + ideaIdCanvas).parent().remove();
  1693. // console.log("The idea \"" + ideaIdCanvas + "\" has been removed");
  1694. }
  1695. }
  1696. // Limit the text in the idea field if it reaches the max length
  1697. limitLengthOnInput();
  1698. // If the user is a collaborator
  1699. if(userIsCollaborator === true) {
  1700. // Show the idea buttons
  1701. $("ul.item_list span.glyphicon").show();
  1702. // Change the cursor
  1703. $("ul.item_list div.expandable").css("cursor", "pointer");
  1704. // Toggle textarea.expandable/div.expandable on focus
  1705. toggleTextElementOnFocus();
  1706. // Show "Tag selected term" link in the destination category
  1707. // For every list of ideas
  1708. $(".card .item_list").each(function() {
  1709. // If the list of ideas has ideas
  1710. if($(this).find("li.added_item").length) {
  1711. // Show "Tag selected term"
  1712. $(this).next().show();
  1713. }
  1714. });
  1715. }
  1716. // Get the tags from the database and apply them on the canvas
  1717. getTags();
  1718. });
  1719. }
  1720. }
  1721. /* ================================================
  1722. Toggle the introduction text in fields
  1723. ================================================= */
  1724. // Toggle the introduction text in fields
  1725. /*
  1726. // $(selector).toggle(speed,easing,callback)
  1727. $('.card').on('click', '.intro-toggle', function() {
  1728. var $TogglingText = $($(this).closest('.card').find('.intro'));
  1729. var $Toggler = $($(this).closest('.card').find('.intro-toggle'));
  1730. $TogglingText.toggle('slow', function() {
  1731. // Do this when toggling:
  1732. // the boolean .is(':visible') of the current toggle state
  1733. if($TogglingText.is(':visible')) {
  1734. // change the text of the toggle
  1735. $Toggler.find('.intro-toggle-text').text('Hide description');
  1736. // change the icon of the toggle
  1737. $Toggler.find('.intro-toggle-icon').switchClass("glyphicon-plus-sign", "glyphicon-minus-sign", 1000, "easeInOutQuad");
  1738. }
  1739. else {
  1740. $Toggler.find('.intro-toggle-text').text('Show description');
  1741. $Toggler.find('.intro-toggle-icon').switchClass("glyphicon-minus-sign", "glyphicon-plus-sign", 1000, "easeInOutQuad");
  1742. }
  1743. });
  1744. });
  1745. */
  1746. /* ================================================
  1747. Auto expand user input textareas
  1748. ================================================= */
  1749. // Works for textareas already existing in the HTML when the page loads -> User input
  1750. /*
  1751. $.each($('textarea[data-autoresize]'), function() {
  1752. var offset = this.offsetHeight - this.clientHeight;
  1753. var resizeTextarea = function(el) {
  1754. $(el).css('height', 'auto').css('height', el.scrollHeight + offset);
  1755. };
  1756. $(this).on('keyup input', function() {
  1757. resizeTextarea(this);
  1758. }).removeAttr('data-autoresize');
  1759. });
  1760. */
  1761. /* ================================================
  1762. Limiting the number of lines in textareas
  1763. ================================================= */
  1764. // Limiting the number of lines in textareas
  1765. /*
  1766. // <textarea data-limit-rows="true" cols="60" rows="8"></textarea>
  1767. $('.card').on('keypress', 'textarea[data-limit-rows=true]', function(event) {
  1768. var textarea = $(this),
  1769. text = textarea.val(),
  1770. // match() -> Searches a string for a match against a regular expression, and returns the matches, as an Array object.
  1771. numberOfLines = (text.match(/\n/g) || []).length + 1,
  1772. maxRows = parseInt(textarea.attr('rows'));
  1773. // if the number of lines have reached the max rows
  1774. if(numberOfLines === maxRows) {
  1775. return false;
  1776. }
  1777. });
  1778. */
  1779. /* ================================================
  1780. Handling user input, ADD items
  1781. A. Add button
  1782. B. Clicking enter
  1783. ================================================= */
  1784. /* ----------------------------------------------
  1785. Add new idea slide effect
  1786. ----------------------------------------------- */
  1787. // When clicking on "add a new idea", Slide down and show the input field for adding a new item (from the begining, it is set to display:hidden with CSS). If clicked again, slide it up. After that, set the textarea in automatic focus
  1788. $('.card').on('click', 'a.add-idea', function(event) {
  1789. // Stop the default behavior of the link (jumping back to the start of the page)
  1790. event.preventDefault();
  1791. // Set the textarea automatically in focus
  1792. $(this).closest('.card').find('.user-input').slideToggle("slow", function() {
  1793. // When the toggle animation is complete:
  1794. // Set the text area in focus
  1795. $(this).closest('.card').find('.new_item').val('');
  1796. $(this).closest('.card').find('.chars').text(maxLength);
  1797. $(this).closest('.card').find('.new_item').focus();
  1798. });
  1799. });
  1800. /* ----------------------------------------------
  1801. A. When we click the add btn to
  1802. add the item to the list
  1803. ----------------------------------------------- */
  1804. // Event deligation to handle the present and future elements that are dynamically added
  1805. $('.card').on('click', '.add_btn', function() {
  1806. var new_item = $(this).closest('.card').find('.new_item').val();
  1807. var new_item_height = $(this).closest('.card').find('.new_item').height();
  1808. // Number of items are in the list
  1809. var fieldItemCount = $(this).closest('.card').find('ul.item_list').find('li').length;
  1810. // New item added, increment the number of items
  1811. fieldItemCount++;
  1812. // Add the input value as a textarea item
  1813. // Create a name attribute in the "field_nr[]" format to be able to tag each new item with the right field attr name (based on the field they are added to). This is to format the json file for each group of dynamically added items. We get the name attribute directly from the id attribute of the ul list in each card (the one we pressed the add button in)
  1814. // If the new item input exist (is not empty), add the item
  1815. if(new_item) {
  1816. var field_attr = $(this).closest('.card').find('ul.item_list').attr('id') + '[]';
  1817. // The height of the newly added item = the height of the add new idea textarea
  1818. $(this).closest('.card').find('ul.item_list').append(
  1819. '<li class="added_item"><div class="expandable" id="' + generateId() + '" name="' + field_attr + '">' + new_item + '</div><br /><span class="comment glyphicon glyphicon-public glyphicon-comment"></span><span class="handle glyphicon glyphicon-list"></span><span class="move-up glyphicon glyphicon-chevron-up"></span><span class="move-down glyphicon glyphicon-chevron-down"></span><span class="remove glyphicon glyphicon-remove-circle"></span></li>'
  1820. );
  1821. // Fix the heights only after a new item is added
  1822. // fixHeights();
  1823. }
  1824. // Clear the new item the text area value
  1825. $(this).closest('.card').find('.new_item').val('');
  1826. // When clicking on "add idea", hide the input field for adding a new item (slideUp() doesn't work nicely here)
  1827. $(this).closest('.card').find('.user-input').hide("fast", function() {
  1828. // Animation complete
  1829. });
  1830. // Show the idea buttons
  1831. $("ul.item_list span.glyphicon").show();
  1832. // Change the cursor
  1833. $("ul.item_list div.expandable").css("cursor", "pointer");
  1834. // Limit the text in the idea field if it reaches the max length
  1835. limitLengthOnInput();
  1836. // Toggle textarea.expandable/div.expandable on edit
  1837. toggleTextElementOnFocus();
  1838. // Remove all tags from all fields
  1839. removeTags();
  1840. // Get the tags from the database and apply them on the canvas
  1841. getTags();
  1842. // If the list of ideas has ideas
  1843. if($(this).parent().parent().prev().prev().children().length > 0) {
  1844. // Show "Tag selected term" link
  1845. $(this).parent().parent().prev().css("display", "block");
  1846. }
  1847. // Save the canvas automatically if the user has logged in
  1848. prepareSaveCanvas();
  1849. });
  1850. /* ----------------------------------------------
  1851. B. Clicking enter in the add idea textarea,
  1852. will add the new item to the card
  1853. ----------------------------------------------- */
  1854. $('.card').on('keypress', 'textarea[data-limit-rows=true]', function(event) {
  1855. var textarea = $(this);
  1856. var text = textarea.val();
  1857. /* The jQuery event.which -->
  1858. Returns which keyboard key was pressed: */
  1859. // If the enter is pressed, event.which === 13
  1860. if(event.which === 13 && !$("li.added_item .expandable").is(":focus")) {
  1861. var new_item = $(this).closest('.card').find('.new_item').val();
  1862. var new_item_height = $(this).closest('.card').find('.new_item').height();
  1863. // Number of items are in the list
  1864. var fieldItemCount = $(this).closest('.card').find('ul.item_list')
  1865. .find('li').length;
  1866. // New item added, increment the number of items
  1867. fieldItemCount++;
  1868. // Add the input value as a textarea item
  1869. // Create a name attribute in the "field_nr[]" format to be able to tag each new item with the right field attr name (based on the field they are added to). This is to format the json file for each group of dynamically added items. We get the name attribute directly from the id attribute of the ul list in each card (the one we pressed the add button in)
  1870. // If the new item input exist (is not empty), add the item
  1871. if(new_item) {
  1872. var field_attr = $(this).closest('.card').find('ul.item_list').attr(
  1873. 'id') + '[]';
  1874. // The height of the newly added item = the height of the add new idea textarea
  1875. $(this).closest('.card').find('ul.item_list').append(
  1876. '<li class="added_item"><div class="expandable" id="' + generateId() + '" name="' + field_attr + '">' + new_item + '</div><br /><span class="comment glyphicon glyphicon-public glyphicon-comment"></span><span class="handle glyphicon glyphicon-list"></span><span class="move-up glyphicon glyphicon-chevron-up"></span><span class="move-down glyphicon glyphicon-chevron-down"></span><span class="remove glyphicon glyphicon-remove-circle"></span></li>'
  1877. );
  1878. // Fix the heights only after a new item is added
  1879. // fixHeights();
  1880. }
  1881. // Clear the new item the text area value
  1882. $(this).closest('.card').find('.new_item').val('');
  1883. // When clicking on "add idea", hide the input field for adding a new item (slideUp() doesn't work nicely here)
  1884. $(this).closest('.card').find('.user-input').hide("fast", function() {
  1885. // Animation complete
  1886. });
  1887. // Show the idea buttons
  1888. $("ul.item_list span.glyphicon").show();
  1889. // Change the cursor
  1890. $("ul.item_list div.expandable").css("cursor", "pointer");
  1891. // Limit the text in the idea field if it reaches the max length
  1892. limitLengthOnInput();
  1893. // Toggle textarea.expandable/div.expandable on edit
  1894. toggleTextElementOnFocus();
  1895. // Remove all tags from all fields
  1896. removeTags();
  1897. // Get the tags from the database and apply them on the canvas
  1898. getTags();
  1899. // If the list of ideas has ideas
  1900. if($(this).parent().parent().parent().prev().prev().children().length > 0) {
  1901. // Show "Tag selected term" link
  1902. $(this).parent().parent().parent().prev().css("display", "block");
  1903. }
  1904. // Save the canvas automatically if the user has logged in
  1905. prepareSaveCanvas();
  1906. }
  1907. });
  1908. /* ================================================
  1909. Commenting ideas
  1910. ================================================= */
  1911. // Remove the comment
  1912. function deleteComment(commentId) {
  1913. // AJAX
  1914. $.ajax({
  1915. type: "POST",
  1916. url: "php/delete-comment.php",
  1917. dataType: "TEXT",
  1918. data: {
  1919. "comment_id": commentId
  1920. },
  1921. timeout: 5000,
  1922. success: function() {
  1923. // Get comments
  1924. getComments();
  1925. },
  1926. error: function(xhr) {
  1927. console.log(xhr.statusText);
  1928. }
  1929. });
  1930. }
  1931. // Get comments
  1932. function getComments() {
  1933. // AJAX
  1934. $.ajax({
  1935. type: "POST",
  1936. url: "php/get-comments.php",
  1937. dataType: "JSON",
  1938. data: {
  1939. "canvas_id": canvasId,
  1940. "idea_id": currentCommentsId
  1941. },
  1942. timeout: 5000,
  1943. success: function(returnData) {
  1944. // If comments exist
  1945. if(returnData.length > 0) {
  1946. // Declarations
  1947. var newHtml = "<tr><th>Comment</th><th>Delete</th></tr>";
  1948. var index = 0;
  1949. // While there still are comments to append
  1950. while(index < returnData.length) {
  1951. newHtml += "<tr id='" + returnData[index]["id"] + "'><td><p class='comments-comment'>" + returnData[index]["comment"] + "</p><p class='comments-by'>by <span class='comments-name'>" + returnData[index]["name"] + "</span> on " + returnData[index]["date"] + "</p></td><td>"
  1952. // If the current collaborator who commented is the active user
  1953. if(returnData[index]["collaborator"] === username) {
  1954. // Add the remove icon
  1955. newHtml += "<span class='glyphicon glyphicon-remove-sign'></span>";
  1956. }
  1957. newHtml += "</td></tr>";
  1958. // Increment the index
  1959. index++;
  1960. }
  1961. // Fix the margin-bottom of the heading
  1962. $("h2#comments-thread-heading").css("margin-bottom", "0.4em");
  1963. // Show the table
  1964. $("table#comments-thread").show();
  1965. // Hide the default text
  1966. $("div#comments-window p#comments-none").hide();
  1967. // Remove all previous comments
  1968. $("table#comments-thread tr").remove();
  1969. // Append the comments
  1970. $("table#comments-thread").append(newHtml);
  1971. // If the user clicks on the "Remove Comment" button
  1972. $("div#comments-window td span").on("click", function() {
  1973. // Declarations
  1974. var commentId = $(this).parent().parent().prop("id");
  1975. // Remove the comment
  1976. deleteComment(commentId);
  1977. });
  1978. // If the user is a collaborator or the owner of the canvas
  1979. if(userIsCollaborator === true || canvasOwner === username) {
  1980. // Show the "Resolve Comments" button
  1981. $("div#comments-window button#comments-resolve").css("display", "block");
  1982. }
  1983. // If the user is not a collaborator
  1984. else {
  1985. // Fix the margin below the table
  1986. $("table#comments-thread").css("margin-bottom", 0);
  1987. }
  1988. }
  1989. // If there are no comments
  1990. else {
  1991. // Fix the margin-bottom of the heading
  1992. $("h2#comments-thread-heading").css("margin-bottom", "0");
  1993. // Show the table
  1994. $("table#comments-thread").hide();
  1995. // Hide the default text
  1996. $("div#comments-window p#comments-none").show();
  1997. // Remove all previous comments
  1998. $("table#comments-thread tr").remove();
  1999. // Show the "Resolve Comments" button
  2000. $("div#comments-window button#comments-resolve").hide();
  2001. }
  2002. },
  2003. error: function(xhr) {
  2004. console.log(xhr.statusText);
  2005. }
  2006. });
  2007. }
  2008. // If the user clicks on the "Comment" icon, show the comments window
  2009. $(".card").on("click", "span.comment", function() {
  2010. // If the user is logged in
  2011. if($("input[name='username']").val() != "") {
  2012. // Show the move window
  2013. $("div#shadow").css("display", "block");
  2014. $("div#comments-window").css("display", "block");
  2015. // Remember the ID of the idea
  2016. currentCommentsId = $(this).parent().find("div").prop("id");
  2017. // Get commments
  2018. getComments();
  2019. updateRemainingCharacters();
  2020. }
  2021. // If the user isn't logged in
  2022. else {
  2023. // Show a dialog
  2024. $("div#shadow").css("display", "block");
  2025. $("div#dialog-log-in").css("display", "block");
  2026. }
  2027. });
  2028. // Close the comments window
  2029. function closeCommentsWindow() {
  2030. // Close the comments window
  2031. $("div#shadow").css("display", "none");
  2032. $("div#comments-window").css("display", "none");
  2033. $("div#comments-window textarea#comments-new").val("Please enter a comment...");
  2034. }
  2035. // If the user clicks on the "Close" button
  2036. $("div#comments-window button.close").on("click", function() {
  2037. // Close the comments window
  2038. closeCommentsWindow();
  2039. });
  2040. // If the user focuses in the textarea
  2041. $("div#comments-window textarea#comments-new").on("focusin", function() {
  2042. // Declarations
  2043. var comment = $("div#comments-window textarea#comments-new").val();
  2044. // If a comment hasn't been entered
  2045. if(comment === "Please enter a comment...") {
  2046. // Empty the comment textarea
  2047. $("div#comments-window textarea#comments-new").val("");
  2048. }
  2049. });
  2050. // If the user leaves the textarea
  2051. $("div#comments-window textarea#comments-new").on("focusout", function() {
  2052. // Declarations
  2053. var comment = $("div#comments-window textarea#comments-new").val();
  2054. // If a comment hasn't been entered
  2055. if(comment === "") {
  2056. // Reset the comment textarea
  2057. $("div#comments-window textarea#comments-new").val("Please enter a comment...");
  2058. }
  2059. });
  2060. // Updating the remaining characters information
  2061. function updateRemainingCharacters() {
  2062. // Declarations
  2063. var length = $("div#comments-window textarea#comments-new").val().length;
  2064. var maxLength = 200;
  2065. // Update length
  2066. length = maxLength - length;
  2067. // If the text isn't the default text
  2068. if($("div#comments-window textarea#comments-new").val() !== "Please enter a comment...")
  2069. // Show the remaining characters
  2070. $("div#comments-window span.chars").text(length);
  2071. // If the text is the default text
  2072. else {
  2073. $("div#comments-window span.chars").text(maxLength);
  2074. }
  2075. }
  2076. // If the user presses a key in the comments textarea
  2077. $("div#comments-window textarea#comments-new").on("keyup", function() {
  2078. // Update remaining characters
  2079. updateRemainingCharacters();
  2080. });
  2081. // If the user clicks on the "Post comment" button
  2082. $("div#comments-window button#comments-post").on("click", function() {
  2083. // Declarations
  2084. var comment = $("div#comments-window textarea#comments-new").val();
  2085. // If a comment has been entered
  2086. if(comment != "" && comment != "Please enter a comment...") {
  2087. // AJAX
  2088. $.ajax({
  2089. timeout: 5000,
  2090. dataType: "json",
  2091. type: "post",
  2092. data: {
  2093. "canvas_id": canvasId,
  2094. "collaborator": username,
  2095. "idea_id": currentCommentsId,
  2096. "comment": comment
  2097. },
  2098. url: "php/post-comment.php",
  2099. success: function() {
  2100. // Empty the textarea
  2101. $("div#comments-window textarea#comments-new").val("Please enter a comment...");
  2102. getComments();
  2103. // Update reamining characters
  2104. updateRemainingCharacters();
  2105. },
  2106. error: function(xhr) {
  2107. console.log(xhr.statusText);
  2108. }
  2109. });
  2110. }
  2111. });
  2112. // Resolve the comments
  2113. function resolveComments() {
  2114. // AJAX
  2115. $.ajax({
  2116. type: "POST",
  2117. url: "php/resolve-comments.php",
  2118. dataType: "TEXT",
  2119. data: {
  2120. "idea_id": currentCommentsId
  2121. },
  2122. timeout: 5000,
  2123. success: function() {
  2124. // Close the Delete Comment window
  2125. $("div#shadow").css("z-index", "2");
  2126. $("div#dialog-resolve-comments").css("display", "none");
  2127. // Get comments
  2128. getComments();
  2129. },
  2130. error: function(xhr) {
  2131. console.log(xhr.statusText);
  2132. }
  2133. });
  2134. }
  2135. // If the user clicks on the "Remove" button
  2136. function showResolveCommentsDialog() {
  2137. // Show the Remove comment dialog
  2138. $("div#shadow").css("z-index", "3");
  2139. $("div#dialog-resolve-comments").css("display", "block");
  2140. // If the user clicks on "Yes"
  2141. $("#dialog-resolve-comments #button-yes").on("click", function() {
  2142. // Resolve the comments
  2143. resolveComments();
  2144. });
  2145. // If the user clicks on "Cancel"
  2146. $("#dialog-resolve-comments #button-cancel").on("click", function() {
  2147. // Cancel
  2148. $("div#shadow").css("z-index", "2");
  2149. $("div#dialog-resolve-comments").css("display", "none");
  2150. });
  2151. }
  2152. // If the user clicks on the "Close" button in the Remove Collaborator dialog
  2153. $("div#dialog-resolve-comments button.close").on("click", function() {
  2154. // Close the Remove Collaborator window
  2155. $("div#shadow").css("z-index", "2");
  2156. $("div#dialog-resolve-comments").css("display", "none");
  2157. });
  2158. // If the user clicks on the "Resolve comments" button
  2159. $("div#comments-window button#comments-resolve").on("click", function() {
  2160. showResolveCommentsDialog();
  2161. });
  2162. /* ================================================
  2163. Moving ideas to a different category
  2164. ================================================= */
  2165. // Declarations
  2166. var categoryDestination;
  2167. var categoryLis = $("div#move-window ul").html();
  2168. var categoryAs = $("div#move-window ul a");
  2169. var categoryOrigin;
  2170. var ideaLi;
  2171. var linkLi;
  2172. var linkText;
  2173. // Remove the link to the current category, as the idea cannot be moved to its own category where it already is
  2174. function removeLinkToOriginCategory(text) {
  2175. // If the number of the category is between 10-99
  2176. if(text.substring(6, 7) != "0") {
  2177. // Remember the origin category
  2178. categoryOrigin = text.substring(6, 9) - 1;
  2179. }
  2180. // If the number of the category is between 0-9
  2181. else {
  2182. // Remember the origin category
  2183. categoryOrigin = text.substring(7, 9) - 1;
  2184. }
  2185. // Remove A tag
  2186. linkLi = $("div#move-window ul li").get(categoryOrigin);
  2187. linkText = categoryAs.get(categoryOrigin).innerHTML;
  2188. linkLi.innerHTML = linkText;
  2189. }
  2190. // If the user clicks on the "Move" icon, show the move window
  2191. $(".card").on("click", "span.handle", function() {
  2192. // Show the move window
  2193. $("div#shadow").css("display", "block");
  2194. $("div#move-window").css("display", "block");
  2195. // Assign the idea that is going to be moved
  2196. ideaLi = $(this).parent();
  2197. // Remove the link to the current category, as the idea cannot be moved to its own category where it already is
  2198. removeLinkToOriginCategory($(this).parent().parent().attr("id"));
  2199. });
  2200. // Close the move window
  2201. function closeMoveWindow() {
  2202. // Close the move window
  2203. $("div#shadow").css("display", "none");
  2204. $("div#move-window").css("display", "none");
  2205. }
  2206. // If the user clicks on the "Close" button
  2207. $("div#move-window button.close").on("click", function() {
  2208. // Close the move window
  2209. closeMoveWindow();
  2210. });
  2211. // If the user clicks on a category, move the idea
  2212. function moveIdeaOnClick() {
  2213. $("div#move-window ul a").on("click", function() {
  2214. // If the number of the category is between 10-99
  2215. if($(this).parent().text().trim().substring(1, 2) != ".") {
  2216. // Remember the destination category
  2217. categoryDestination = $(this).parent().text().trim().substring(0, 2);
  2218. }
  2219. // If the number of the category is between 0-9
  2220. else {
  2221. // Remember the destination category
  2222. categoryDestination = $(this).parent().text().trim().substring(0, 1);
  2223. }
  2224. // If the number of the category is between 10-99
  2225. if(categoryDestination > 9) {
  2226. // Move the idea
  2227. $("ul#field_" + categoryDestination).append(ideaLi);
  2228. }
  2229. // If the number of the category is between 0-9
  2230. else {
  2231. // Move the idea
  2232. $("ul#field_0" + categoryDestination).append(ideaLi);
  2233. }
  2234. // Close the move window
  2235. closeMoveWindow();
  2236. // Save the canvas automatically if the user has logged in
  2237. prepareSaveCanvas();
  2238. // If the Move window isn't opened for the first time
  2239. if($("div#move-window li").length > $("div#move-window a").length) {
  2240. // Restore links in the move window
  2241. $("div#move-window ul").children().remove()
  2242. $("div#move-window ul").append(categoryLis);
  2243. moveIdeaOnClick();
  2244. }
  2245. // Hide "Tag selected term" link in the origin category if there are no ideas left
  2246. if($("ul#field_0" + (categoryOrigin + 1)).children().length === 0) {
  2247. // If the number of the category is between 10-99
  2248. if((categoryOrigin + 1) > 9) {
  2249. // Hide the "Tag selected term" button
  2250. $("ul#field_" + (categoryOrigin + 1)).parent().find("p.tag-selected-term").css("display", "none");
  2251. }
  2252. // If the number of the category is between 0-9
  2253. else {
  2254. // Hide the "Tag selected term" button
  2255. $("ul#field_0" + (categoryOrigin + 1)).parent().find("p.tag-selected-term").css("display", "none");
  2256. }
  2257. }
  2258. // If the user is a collaborator
  2259. if(userIsCollaborator === true) {
  2260. // Show "Tag selected term" link in the destination category
  2261. // If the number of the category is between 10-99
  2262. if((categoryOrigin + 1) > 9) {
  2263. $("ul#field_" + categoryDestination).parent().find("p.tag-selected-term").css("display", "block");
  2264. }
  2265. // If the number of the category is between 0-9
  2266. else {
  2267. $("ul#field_0" + categoryDestination).parent().find("p.tag-selected-term").css("display", "block");
  2268. }
  2269. }
  2270. });
  2271. }
  2272. moveIdeaOnClick();
  2273. /* ================================================
  2274. Moving ideas up
  2275. ================================================= */
  2276. // If the user clicks on the "Up" button
  2277. $('.card').on('click', 'span.move-up', function() {
  2278. // Declarations
  2279. var ideaLiCurrent = $(this).parent();
  2280. var ideaLiPrevious = $(this).parent().prev();
  2281. // If the previous element is a list item
  2282. if(ideaLiPrevious.is("li")) {
  2283. // Move the idea
  2284. ideaLiCurrent.detach();
  2285. ideaLiPrevious.before(ideaLiCurrent);
  2286. // Save the canvas automatically if the user has logged in
  2287. prepareSaveCanvas();
  2288. }
  2289. });
  2290. /* ================================================
  2291. Moving ideas down
  2292. ================================================= */
  2293. // If the user clicks on the "Down" button
  2294. $('.card').on('click', 'span.move-down', function() {
  2295. // Declarations
  2296. var ideaLiCurrent = $(this).parent();
  2297. var ideaLiNext = $(this).parent().next();
  2298. // If the previous element is a list item
  2299. if(ideaLiNext.is("li")) {
  2300. // Move the idea
  2301. ideaLiCurrent.detach();
  2302. ideaLiNext.after(ideaLiCurrent);
  2303. // Save the canvas automatically if the user has logged in
  2304. prepareSaveCanvas();
  2305. }
  2306. });
  2307. /* ================================================
  2308. Deleting ideas
  2309. ================================================= */
  2310. var ideaToDelete;
  2311. function deleteIdea() {
  2312. // If there are no ideas left
  2313. if(ideaToDelete.prev().parent().parent().children().length === 1) {
  2314. // Hide "Tag selected term" link
  2315. ideaToDelete.prev().parent().parent().next().css("display", "none");
  2316. }
  2317. // Remove the list item
  2318. ideaToDelete.closest("li").remove();
  2319. // Save the canvas automatically if the user has logged in
  2320. prepareSaveCanvas();
  2321. }
  2322. function showDeleteIdeaDialog() {
  2323. // Show a dialog
  2324. $("div#shadow").css("display", "block");
  2325. $("div#dialog-delete-idea").css("display", "block");
  2326. }
  2327. // If the user clicks on "Yes" button in the Delete Comment dialog
  2328. $("div#dialog-delete-idea #button-yes").on("click", function() {
  2329. // Resolve the comments
  2330. resolveComments();
  2331. // Delete the idea
  2332. deleteIdea();
  2333. // Update view
  2334. $("div#shadow").css("display", "none");
  2335. $("div#dialog-delete-idea").css("display", "none");
  2336. });
  2337. // If the user clicks on "Cancel" button in the Delete Comment dialog
  2338. $("div#dialog-delete-idea #button-cancel").on("click", function() {
  2339. // Cancel
  2340. $("div#shadow").css("display", "none");
  2341. $("div#dialog-delete-idea").css("display", "none");
  2342. });
  2343. // If the user clicks on the "Close" button in the Delete Comment dialog
  2344. $("div#dialog-delete-idea button.close").on("click", function() {
  2345. // Close the Delete Comment window
  2346. $("div#shadow").css("display", "none");
  2347. $("div#dialog-delete-idea").css("display", "none");
  2348. });
  2349. // If the cross beside the textarea is clicked, remove that list item
  2350. $('.card').on('click', 'span.remove', function() {
  2351. ideaToDelete = $(this);
  2352. // Remember the ID of the idea
  2353. currentCommentsId = ideaToDelete.parent().find("div").prop("id");
  2354. // AJAX
  2355. $.ajax({
  2356. type: "POST",
  2357. url: "php/check-comments.php",
  2358. dataType: "JSON",
  2359. data: {
  2360. "canvas_id": canvasId,
  2361. "idea_id": currentCommentsId
  2362. },
  2363. timeout: 5000,
  2364. success: function(returnData) {
  2365. // If the idea has comments
  2366. if(returnData.length > 0) {
  2367. showDeleteIdeaDialog();
  2368. }
  2369. else {
  2370. deleteIdea();
  2371. }
  2372. },
  2373. error: function(xhr) {
  2374. console.log(xhr.statusText);
  2375. }
  2376. });
  2377. });
  2378. /* ================================================
  2379. Sortable field ideas
  2380. ================================================= */
  2381. // Make items sortable in their fields and between fields
  2382. /*
  2383. $('.sortable').sortable({
  2384. connectWith: '.connectedList',
  2385. placeholder: "sort-placeholder",
  2386. // revert: true
  2387. zIndex: 300 // Or greater than any other relative/absolute/fixed elements and droppables
  2388. });
  2389. */
  2390. /* ================================================
  2391. Sorting and Dragging events
  2392. ================================================= */
  2393. // Every textarea in a item needs to get the right name attribute once they have been dropped in another field (so it ends up in the right place in the json file)
  2394. /*
  2395. // Dragging starts
  2396. $(".sortable").on("sortstart", function(event, ui) {
  2397. // WHEN WE SORT CARDS, $(this) ---> the "begining" ul with the class of .sortable
  2398. });
  2399. // Dragging ends: item dropped
  2400. $(".sortable").on("sortstop", function(event, ui) {
  2401. // get the id of the field ul (to set the name attribute of textareas)
  2402. // # mouseleave is the right event for when we release and leave a card mouseup doesn't work properly in this case
  2403. $('.card').on('mouseleave', 'li', function() {
  2404. //$(selector).attr(attribute,value)
  2405. var fieldAttr = $(this).closest('ul.item_list').attr('id');
  2406. // $(this).find('textarea').attr('name', fieldAttr + '[]');
  2407. $(this).find('li.added_item .expandable').attr('name', fieldAttr + '[]');
  2408. });
  2409. });
  2410. */
  2411. /* ================================================
  2412. Update the project and date title of the canvas in the database
  2413. ================================================= */
  2414. // Update the project and date title of the canvas in the database
  2415. function updateProjectTitleInDatabase() {
  2416. // Declarations
  2417. var projectTitle = $("div.form-header input.proj_title").val();
  2418. // AJAX
  2419. $.ajax({
  2420. async: false,
  2421. timeout: 5000,
  2422. dataType: "text",
  2423. type: "post",
  2424. data: {
  2425. "canvas_id": canvasId,
  2426. "project_title": projectTitle,
  2427. "current_date": currentDate
  2428. },
  2429. url: "php/update-project-in-database.php",
  2430. error: function(xhr) {
  2431. console.log(xhr.statusText);
  2432. }
  2433. });
  2434. }
  2435. /* ================================================
  2436. SAVING THE CANVAS:
  2437. CLICK ON #EXPORT JSON# form button
  2438. ================================================= */
  2439. // Save the canvas
  2440. function saveCanvas() {
  2441. /* ----------------------------------------------
  2442. A: Saving the canvas
  2443. as a registered user
  2444. ----------------------------------------------- */
  2445. // PHP variables are retieved in the header of the canvas index.php as js variables -->
  2446. var name_save_canvas = $('.form-header').find('.proj_title').val();
  2447. // var date_save_canvas = $('.form-header').find('.proj_date').val();
  2448. var date_save_canvas = currentDate;
  2449. var save_canvas_obj;
  2450. // If canvasOwner isn't empty
  2451. if(canvasOwner !== "") {
  2452. save_canvas_obj = {
  2453. 'email_save_canvas': canvasOwner,
  2454. 'name_save_canvas': name_save_canvas,
  2455. 'date_save_canvas': date_save_canvas,
  2456. 'id_save_canvas': canvasId
  2457. };
  2458. }
  2459. // If this is the first time saving the canvas
  2460. else {
  2461. console.log("The canvas is about to be saved for the first time");
  2462. save_canvas_obj = {
  2463. 'email_save_canvas': email_save_canvas,
  2464. 'name_save_canvas': name_save_canvas,
  2465. 'date_save_canvas': date_save_canvas,
  2466. 'id_save_canvas': canvasId
  2467. };
  2468. }
  2469. var save_canvas = $.param(save_canvas_obj);
  2470. // Post the JSON stringified object to the php file (the PHP script will save it in a .json file )
  2471. var save_reg_url = "php/save-canvas.php";
  2472. $.post(save_reg_url, { save_canvas: save_canvas }, function(data, status) {
  2473. // If the returned data is successful, it is the $canvas_id
  2474. var canvas_id = data;
  2475. // Send this canvas_id with the next AJAX request to the php/canvas.php file and use it as the name of the JSON file to be saved
  2476. /* ----------------------------------------------
  2477. For the second AJAX request:
  2478. B: Exporting the form data JSON to a file
  2479. and save it on the server
  2480. ----------------------------------------------- */
  2481. // $('#result').text(JSON.stringify($('.canvas-form').serializeObject()));
  2482. // Make the JSON object into a JSON string
  2483. // var JSONstrObj = JSON.stringify($('.canvas-form').serializeObject());
  2484. var JSONstrObj = JSON.stringify($('.canvas-form').serializeObject());
  2485. var url = "php/canvas.php";
  2486. // Post the JSON stringified object to the php file (the php script will save it in a .json file)
  2487. // Also, send the canvas_id and use it for naming the file
  2488. $.post(url, {
  2489. JSONstrObj: JSONstrObj,
  2490. canvas_id: canvas_id
  2491. }, function(data, status) {
  2492. console.log(
  2493. 'Response from PHP when sending the form JSON object: \n' +
  2494. 'data:' + data + '\n status: ' + status);
  2495. // Update the project title in the database
  2496. updateProjectTitleInDatabase();
  2497. // If the canvas is saved for the first time
  2498. if(numberOfCollaborators === 0) {
  2499. // Show the Collaborators button
  2500. $(".form-header #collaborators-container").show();
  2501. // Add the owner to Collaborators in the database
  2502. addOwnerToCollaborators();
  2503. // Get the owner
  2504. getOwner();
  2505. // Update the Collaborators table
  2506. updateCollaborators();
  2507. // Update owner
  2508. $("p#canvas-owner").text(canvasOwner);
  2509. }
  2510. // Remember that the canvas isn't new
  2511. canvasIsNew = false;
  2512. }).fail(function(jqXHR) {
  2513. console.log("Error " + jqXHR.status + ' ' + jqXHR.statustext);
  2514. });
  2515. }).fail(function(jqXHR) {
  2516. console.log("Error " + jqXHR.status + ' ' + jqXHR.statustext);
  2517. });
  2518. // Prevent the card item list from reseting itself after clicking on the export button (submission). Because the type of the button is submit
  2519. return false;
  2520. }
  2521. /* ----------------------------------------------
  2522. Save the canvas if the user has logged in
  2523. ----------------------------------------------- */
  2524. // Prepare to save the canvas
  2525. function prepareSaveCanvas() {
  2526. // If the viewer of the canvas is a logged in user
  2527. if($("input[name='username']").val() != "") {
  2528. // Save the canvas
  2529. saveCanvas();
  2530. }
  2531. }
  2532. // Save the canvas on load
  2533. // prepareSaveCanvas();
  2534. /* ================================================
  2535. Create and remove hidden copies of every list item.
  2536. These are needed in order to export the canvas as PDF.
  2537. ================================================= */
  2538. // Create an hidden copy of every list item
  2539. function createHiddenLiCopies() {
  2540. // For every idea
  2541. $("li.added_item").each(function() {
  2542. // Declarations
  2543. var oldLiName = $(this).find(".expandable").attr("name");
  2544. var oldLiText = $(this).find(".expandable").text();
  2545. var newLi = "<li class='hidden'><textarea name='" + oldLiName + "'>" + oldLiText + "</textarea></li>";
  2546. // Append the hidden copy
  2547. $(this).after(newLi);
  2548. });
  2549. }
  2550. // Remove the hidden copies of every list item
  2551. function removeHiddenLiCopies() {
  2552. window.setTimeout(function() {
  2553. $("li.hidden").remove();
  2554. }, 1000);
  2555. }
  2556. /* ================================================
  2557. HANDLING CLICK ON: Email This Canvas BUTTON
  2558. ================================================= */
  2559. /*
  2560. // "Email This Canvas" button
  2561. $(".canvas-form").on("click", ".share_canvas", function(event) {
  2562. // Prevent default operation
  2563. event.preventDefault();
  2564. // Create an hidden copy of every list item
  2565. createHiddenLiCopies();
  2566. // Remove the hidden copies of every list item
  2567. removeHiddenLiCopies();
  2568. $(".share_canvas_email").slideToggle(1000, function() {
  2569. // Save the PDF as file
  2570. $.post("mpdf/canvas-save.php", function(data, status) {});
  2571. });
  2572. });
  2573. // "Send" button
  2574. $(".canvas-form").on("click", ".share_canvas_send", function() {
  2575. // Create an hidden copy of every list item
  2576. createHiddenLiCopies();
  2577. // Remove the hidden copies of every list item
  2578. removeHiddenLiCopies();
  2579. var share_email = $(".share_canvas_email").find("input").serialize();
  2580. // This sends a serialized array share_email to the PHP file. Example: the value of this array will be: share-canvas-email=eternalflame.f%40gmail.com
  2581. $.post("php/share-canvas.php", {
  2582. share_email: share_email
  2583. }, function(data, status) {
  2584. // Canvas successfully shared
  2585. if(data == 200) {
  2586. $(".canvas-form").find(".imp-exp-btn ").append("<div class='save-canvas-feedback'><p><span class='glyphicon glyphicon-ok' aria-hidden='true'></span>Your canvas has been shared by email</p></div>");
  2587. }
  2588. // Canvas could not be shared
  2589. else {
  2590. $(".canvas-form").find(".imp-exp-btn ").append("<div class='save-canvas-feedback'><p><span class='glyphicon glyphicon-ok' aria-hidden='true'></span>Your canvas could not be shared</p></div>");
  2591. }
  2592. });
  2593. // Slide up the .share_canvas_email area
  2594. $(".share_canvas_email").slideUp();
  2595. });
  2596. */
  2597. /* ================================================
  2598. HANDLING CLICK ON: Download as PDF
  2599. ================================================= */
  2600. // If the user clicks on "Download as PDF"
  2601. $(".canvas-form").on("click", ".pdf_exp", function() {
  2602. // Create an hidden copy of every list item
  2603. createHiddenLiCopies();
  2604. // Remove the hidden copies of every list item
  2605. removeHiddenLiCopies();
  2606. });
  2607. /* ================================================
  2608. HANDLING CLICK ON: Publish This Canvas BUTTON
  2609. ================================================= */
  2610. // HANDLING CLICK ON: Publish This Canvas BUTTON
  2611. $("button.publish_canvas").on("click", function(event) {
  2612. // Prevent default operation
  2613. event.preventDefault();
  2614. // If the user is logged in
  2615. if($("input[name='username']").val() != "") {
  2616. // AJAX
  2617. $.ajax({
  2618. type: "POST",
  2619. url: "php/toggle-public.php",
  2620. dataType: "TEXT",
  2621. data: {
  2622. "canvas_id": canvasId
  2623. },
  2624. timeout: 5000,
  2625. success: function(returnData) {
  2626. if(returnData === "0") {
  2627. $("button.publish_canvas").text("Publish for viewing/commenting");
  2628. }
  2629. else if(returnData === "1") {
  2630. $("button.publish_canvas").text("Unpublish for viewing/commenting");
  2631. }
  2632. },
  2633. error: function(xhr) {
  2634. console.log(xhr.statusText);
  2635. }
  2636. });
  2637. }
  2638. // If the user isn't logged in
  2639. else {
  2640. // Show a dialog
  2641. $("div#shadow").css("display", "block");
  2642. $("div#dialog-log-in").css("display", "block");
  2643. }
  2644. return false;
  2645. });
  2646. /* ================================================
  2647. Receiving remote updates automatically
  2648. ================================================= */
  2649. // For every 7 seconds
  2650. window.setInterval(function() {
  2651. // If collaborators have been added and the canvas isn't new
  2652. if(numberOfCollaborators > 1 && canvasIsNew === false) {
  2653. console.log("Importing canvas!");
  2654. // Refresh
  2655. importCanvasAgain();
  2656. updateCollaborators();
  2657. checkPublic();
  2658. // If the comments window is open
  2659. if($("div#comments-window").css("display") !== "none") {
  2660. // Get comments
  2661. getComments();
  2662. }
  2663. }
  2664. }, 7000);
  2665. /* ================================================
  2666. Controlling the height of divs dynamically
  2667. ================================================= */
  2668. // Call this function after adding a new item and importing
  2669. /*
  2670. // $( window ).width(); ->Returns width of browser viewport
  2671. function fixHeights() {
  2672. // Returns width of browser viewport
  2673. var screenSize = $(window).width();
  2674. //the longest card of the group 1 .masonry-layout7-5
  2675. var longest_1 = $('.masonry-layout7-5').height();
  2676. //the longest card of the group 2 .masonry-layout7-5
  2677. var longest_2 = $('.masonry-layout4').height();
  2678. // --- 5 COL Range ----
  2679. if(screenSize >= 1139) {
  2680. // inforcing a fixed height ".height(longest_1/2)" will create some layout issues when we try to add new items the add item area will go outside the box and the heights don't increase naturally
  2681. // card group 1:
  2682. // $('.field_05,.field_11, .field_07').css('min-height', longest_1 - longest_1 * 5 / 100);
  2683. // $('.field_06,.field_08, .field_12').css('min-height', longest_1 + longest_1 * 5 / 100);
  2684. // $('.field_01, .field_02').css('min-height', longest_1 * 2 + longest_1 * 1 / 100);
  2685. // card group 2:
  2686. // $('.field_03, .field_09, .field_10, .field_04').css('min-height', longest_2 * 2 - longest_2 * 20 / 100);
  2687. $('.field_05,.field_11, .field_07').css('min-height', longest_1 - longest_1 * 20 / 100);
  2688. $('.field_06,.field_08, .field_12').css('min-height', longest_1 - longest_1 * 20 / 100);
  2689. $('.field_01, .field_02').css('min-height', longest_1 + longest_1 * 40 / 100);
  2690. // card group 2:
  2691. $('.field_03, .field_09, .field_10, .field_04').css('min-height', longest_2 - longest_2 * 10 / 100);
  2692. }
  2693. // 4 COL Range //
  2694. else if(screenSize >= 977 && screenSize <= 1138) {
  2695. // card group 1:
  2696. // row 1
  2697. $('.field_01,.field_06, .field_12,.field_08 ').css('min-height', longest_1 + longest_2 * 20 / 100);
  2698. // row 2
  2699. $('.field_05,.field_11, .field_07,.field_02 ').css('min-height', longest_1 + longest_2 * 20 / 100);
  2700. // card group 2:
  2701. // row 3
  2702. $('.field_03, .field_09, .field_10, .field_04').css('min-height', longest_2 * 2 - longest_2 * 20 / 100);
  2703. } else if(screenSize >= 920 && screenSize <= 976) {
  2704. // card group 1:
  2705. // row 1
  2706. $('.field_01,.field_06, .field_12,.field_08 ').css('min-height', longest_1 + longest_2 * 20 / 100);
  2707. // row 2
  2708. $('.field_05,.field_11, .field_07,.field_02 ').css('min-height', longest_1 + longest_2 * 20 / 100);
  2709. // card group 2:
  2710. // row 3
  2711. $('.field_03, .field_09, .field_10, .field_04').css('min-height', longest_2 * 2 - longest_2 * 20 / 100);
  2712. } else if(screenSize >= 485 && screenSize <= 919) {
  2713. // else if(500 <= screenSize < 920) {
  2714. // card group 1:
  2715. $('.field_01,.field_06, .field_12,.field_08 ').css('min-height', longest_1 * 80 / 100);
  2716. $('.field_05,.field_11, .field_07,.field_02 ').css('min-height', longest_1 * 80 / 100);
  2717. // card group 2:
  2718. $('.field_03, .field_09, .field_10, .field_04').css('min-height', longest_2 * 80 / 100);
  2719. // --- 1 COL Range ----
  2720. } else {
  2721. // card group 1:
  2722. $('.field_01,.field_06, .field_12,.field_08 ').css('min-height', longest_1 * 20 / 100);
  2723. $('.field_05,.field_11, .field_07,.field_02 ').css('min-height', longest_1 * 20 / 100);
  2724. // card group 2:
  2725. $('.field_03, .field_09, .field_10, .field_04').css('min-height', longest_2 * 20 / 100);
  2726. }
  2727. }
  2728. function fixHeights() {
  2729. // Returns width of browser viewport
  2730. var screenSize = $(window).width();
  2731. var field01 = $("div.field_01");
  2732. var field02 = $("div.field_02");
  2733. var field03 = $("div.field_03");
  2734. var field04 = $("div.field_04");
  2735. var field05 = $("div.field_05");
  2736. var field06 = $("div.field_06");
  2737. var field07 = $("div.field_07");
  2738. var field08 = $("div.field_08");
  2739. var field09 = $("div.field_09");
  2740. // Set the height of every field
  2741. var heightOfField01 = field01.height();
  2742. var heightOfField03 = field03.height();
  2743. var heightOfField04 = field04.height();
  2744. var heightOfField03And04 = field03.height() + field04.height();
  2745. var heightOfField09 = field09.height();
  2746. var heightOfField05 = field05.height();
  2747. var heightOfField06 = field06.height();
  2748. var heightOfField05And06 = field05.height() + field06.height();
  2749. var heightOfField02 = field02.height();
  2750. // --- 5 COL Range ---
  2751. if(screenSize >= 935) {
  2752. var longestInGroup1 = Math.max(heightOfField01, heightOfField03, heightOfField04, heightOfField03And04, heightOfField09, heightOfField05, heightOfField06, heightOfField05And06, heightOfField02);
  2753. console.log(longestInGroup1);
  2754. // Field group 1
  2755. switch(longestInGroup1) {
  2756. case heightOfField01:
  2757. $(".field_04").css("min-height", longestInGroup1 + 10);
  2758. $(".field_09").css("min-height", longestInGroup1 + 448);
  2759. $(".field_06").css("min-height", longestInGroup1 + 10);
  2760. $(".field_02").css("min-height", longestInGroup1 + 448);
  2761. break;
  2762. case heightOfField03:
  2763. // Code goes here
  2764. break;
  2765. case heightOfField04:
  2766. // Code goes here
  2767. break;
  2768. case heightOfField03And04:
  2769. // Code goes here
  2770. break;
  2771. case heightOfField09:
  2772. // Code goes here
  2773. break;
  2774. case heightOfField05:
  2775. // Code goes here
  2776. break;
  2777. case heightOfField06:
  2778. // Code goes here
  2779. break;
  2780. case heightOfField05And06:
  2781. // Code goes here
  2782. break;
  2783. case heightOfField02:
  2784. // Code goes here
  2785. break;
  2786. default:
  2787. break;
  2788. }
  2789. }
  2790. // --- 4 COL Range ---
  2791. else if(screenSize >= 935 && screenSize <= 991) {
  2792. // Field group 1
  2793. // Code goes here
  2794. // Field group 2
  2795. // Code goes here
  2796. }
  2797. else if(screenSize >= 992 && screenSize <= 1153) {
  2798. // Field group 1
  2799. // Code goes here
  2800. // Field group 2
  2801. // Code goes here
  2802. }
  2803. // --- 2 COL Range ---
  2804. else if(screenSize >= 500 && screenSize <= 934) {
  2805. // Field group 1
  2806. // Code goes here
  2807. // Field group 2
  2808. // Code goes here
  2809. }
  2810. // --- 2-5 COL Range ---
  2811. if(screenSize >= 500) {
  2812. var longestInGroup2;
  2813. // Field group 2
  2814. // Determine the longest Field in group 2
  2815. if(field07.height() < field08.height()) {
  2816. longestInGroup2 = field08;
  2817. }
  2818. else {
  2819. longestInGroup2 = field07;
  2820. }
  2821. if(longestInGroup2 === field07) {
  2822. $(".field_08").css("min-height", longestInGroup2.height() + 10);
  2823. }
  2824. else {
  2825. $(".field_07").css("min-height", longestInGroup2.height() + 10);
  2826. }
  2827. }
  2828. // --- 1 COL Range ---
  2829. // Field group 1
  2830. // Code goes here
  2831. // Field group 2
  2832. // Code goes here
  2833. }
  2834. */
  2835. // ResizeSensor
  2836. /*
  2837. new ResizeSensor($(".field_01, .field_02, .field_03, .field_04, .field_05, .field_06, .field_07, .field_08, .field_09"), function() {
  2838. // fixHeights();
  2839. });
  2840. */
  2841. });