window.wagn ||= {} #needed to run w/o *head. eg. jasmine $.extend wagn, editorContentFunctionMap: { '.ace-editor-textarea' : -> ace_editor_content this[0] '.tinymce-textarea' : -> tinyMCE.get(@[0].id).getContent() '.pointer-select' : -> pointerContent @val() '.pointer-multiselect' : -> pointerContent @val() '.pointer-radio-list' : -> pointerContent @find('input:checked').val() '.pointer-list-ul' : -> pointerContent @find('input' ).map( -> $(this).val() ) '.pointer-checkbox-list' : -> pointerContent @find('input:checked').map( -> $(this).val() ) '.pointer-select-list' : -> pointerContent @find('.pointer-select select').map( -> $(this).val() ) '.pointer-mixed' : -> pointerContent @find('.pointer-checkbox-sublist input:checked, .pointer-sublist-ul input').map( -> $(this).val() ) '.perm-editor' : -> permissionsContent this # must happen after pointer-list-ul, I think } editorInitFunctionMap: { '.date-editor' : -> @datepicker { dateFormat: 'yy-mm-dd' } 'textarea' : -> $(this).autosize() '.ace-editor-textarea' : -> wagn.initAce $(this) '.tinymce-textarea' : -> wagn.initTinyMCE @[0].id '.pointer-list-editor' : -> @sortable({handle: '.handle', cancel: ''}); wagn.initPointerList @find('input') '.file-upload' : -> @fileupload( dataType: 'html', done: wagn.doneFile, add: wagn.chooseFile, progressall: wagn.progressallFile )#, forceIframeTransport: true ) '.etherpad-textarea' : -> $(this).closest('form').find('.edit-submit-button').attr('class', 'etherpad-submit-button') } initPointerList: (input)-> optionsCard = input.closest('ul').data('options-card') input.autocomplete { source: wagn.prepUrl wagn.rootPath + '/' + optionsCard + '.json?view=name_complete' } setTinyMCEConfig: (string)-> setter = ()-> try $.parseJSON string catch {} wagn.tinyMCEConfig = setter() initAce: (textarea) -> type_code = textarea.attr "data-card-type-code" hash = {} hash["java_script"] = "javascript" hash["coffee_script"] = "coffee" hash["css"] = "css" hash["scss"] = "scss" hash["html"] = "html" hash["search_type"] = "json" hash["layout_type"] = "html" mode = hash[type_code] unless mode textarea.autosize() return editDiv = $("
", position: "absolute" width: "auto" height: textarea.height() ).insertBefore(textarea) textarea.css "visibility", "hidden" textarea.css "height", "0px" ace.config.set('basePath','/assets/ace') editor = ace.edit(editDiv[0]) editor.renderer.setShowGutter true editor.getSession().setValue textarea.val() editor.setTheme "ace/theme/github" editor.getSession().setMode "ace/mode/" + mode editor.setOption "showPrintMargin", false editor.getSession().setTabSize 2 editor.getSession().setUseSoftTabs true editor.setOptions maxLines: 30 return initTinyMCE: (el_id) -> # verify_html: false -- note: this option needed for empty paragraphs to add space. conf = { plugins: 'autoresize' autoresize_max_height: 500 } user_conf = if wagn.tinyMCEConfig? then wagn.tinyMCEConfig else {} hard_conf = { mode: 'exact' elements: el_id #CSS could be made optional, but it may involve migrating old legacy *tinyMCE settings to get rid of stale stuff. content_css: wagn.cssPath entity_encoding: 'raw' } $.extend conf, user_conf, hard_conf tinyMCE.init conf # Can't get this to work yet. Intent was to tighten up head tag. # initGoogleAnalytics: (key) -> # window._gaq.push ['_setAccount', key] # window._gaq.push ['_trackPageview'] # # initfunc = ()-> # ga = document.createElement 'script' # ga.type = 'text/javascript' # ga.async = true # ga.src = `('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'` # s = document.getElementsByTagName('script')[0] # s.parentNode.insertBefore ga, s # initfunc() chooseFile: (e, data) -> data.form.find('button[type=submit]').attr('disabled',true) editor = $(this).closest '.card-editor' $('#progress').show() editor.append '' editor.append '' data.submit() editor.find('.choose-file').hide() editor.find('.extra_upload_param').remove() progressallFile: (e, data) -> progress = parseInt(data.loaded / data.total * 100, 10) $('#progress .progress-bar').css('width', progress + '%') doneFile: (e, data) -> editor = $(this).closest '.card-editor' editor.find('.chosen-file').replaceWith data.result data.form.find('button[type=submit]').attr('disabled',false) isTouchDevice: -> if 'ontouchstart' of window or window.DocumentTouch and document instanceof DocumentTouch return true else return detectMobileBrowser() # source for this method: detectmobilebrowsers.com detectMobileBrowser = (userAgent) -> userAgent = navigator.userAgent or navigator.vendor or window.opera /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) or /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4)) $(window).ready -> $('body').on 'click', '.cancel-upload', -> editor = $(this).closest '.card-editor' editor.find('.choose-file').show() editor.find('.chosen-file').empty() editor.find('.progress').show() editor.find('#progress .progress-bar').css('width', '0%') editor.find('#progress').hide() #navbox mod $('.navbox').autocomplete { html: 'html', source: navbox_results, select: navbox_select # autoFocus: true, # this makes it so the first option ("search") is pre-selected. # sadly, it also causes odd navbox behavior, resetting the search term } #pointer mod $('body').on 'click', '.pointer-item-add', (event)-> last_item = $(this).closest('.content-editor').find '.pointer-li:last' new_item = last_item.clone() input = new_item.find('input') input.val '' last_item.after new_item wagn.initPointerList(input) event.preventDefault() # Prevent link from following its href $('body').on 'click', '.pointer-item-delete', -> item = $(this).closest 'li' if item.closest('ul').find('.pointer-li').length > 1 item.remove() else item.find('input').val '' $('body').on 'show.bs.tab', 'a.load[data-toggle=tab][data-url]', (e) -> tab_id = $(e.target).attr('href') url = $(e.target).data('url') $(e.target).removeClass('load') $(tab_id).load(url) # toolbar mod $('body').on 'click', '.toolbar-pin.active', (e) -> e.preventDefault() $(this).blur() $('.toolbar-pin').removeClass('active').addClass('inactive') $.ajax '/*toolbar_pinned', type : 'PUT' data : 'card[content]=false' $('body').on 'click', '.toolbar-pin.inactive', (e) -> e.preventDefault() $(this).blur() $('.toolbar-pin').removeClass('inactive').addClass('active') $.ajax '/*toolbar_pinned', type : 'PUT' data : 'card[content]=true' # following mod $('body').on 'click', '.btn-item-delete', -> $(this).find('.glyphicon').addClass("glyphicon-hourglass").removeClass("glyphicon-remove") $('body').on 'click', '.btn-item-add', -> $(this).find('.glyphicon').addClass("glyphicon-hourglass").removeClass("glyphicon-plus") $('body').on 'mouseenter', '.btn-item-delete', -> $(this).find('.glyphicon').addClass("glyphicon-remove").removeClass("glyphicon-ok") $(this).addClass("btn-danger").removeClass("btn-primary") $('body').on 'mouseleave', '.btn-item-delete', -> $(this).find('.glyphicon').addClass("glyphicon-ok").removeClass("glyphicon-remove") $(this).addClass("btn-primary").removeClass("btn-danger") # modal mod $('body').on 'hide.bs.modal', (event) -> $(event.target).find('.modal-dialog > .modal-content').empty() if $(event.target).attr('id') != 'modal-main-slot' slot = $( event.target ).slot() menu_slot = slot.find '.menu-slot:first' url = wagn.rootPath + '/~' + slot.data('card-id') params = { view: 'menu' } params['is_main'] = true if slot.isMain() $.ajax url, { type : 'GET' data: params success : (data) -> menu_slot.replaceWith data } # for slot in $('.card-slot') # menu_slot = $(slot).find '.menu-slot:first' # if menu_slot.size() > 0 # url = wagn.rootPath + '/~' + $(slot).data('card-id') # params = { view: 'menu' } # params['is_main'] = true if $(slot).isMain() # # $.ajax url, { # type: 'GET' # data: params # success : (data) -> # menu_slot.replaceWith data # } # $('body').on 'click', '.update-follow-link', (event) -> # anchor = $(this) # url = wagn.rootPath + '/' + anchor.data('card_key') + '.json?view=follow_status' # modal = anchor.closest('.modal') # modal.removeData() # $.ajax url, { # type : 'GET' # dataType : 'json' # success : (data) -> # tags = $(modal).parent().find('.follow-link') # tags.find('.follow-verb').html data.verb # tags.attr 'href', data.path # tags.attr 'title', data.title # tags.data 'follow', data # } # $('body').on 'click', '.follow-toggle', (event) -> # anchor = $(this) # url = wagn.rootPath + '/update/' + anchor.data('rule_name') + '.json' # $.ajax url, { # type : 'POST' # dataType : 'json' # data : { # 'card[content]' : '[[' + anchor.data('follow').content + ']]' # 'success[view]' : 'follow_status' # 'success[id]' : anchor.data('card_key') # } # success : (data) -> # tags = anchor.closest('.modal').parent().find('.follow-toggle') # tags.find('.follow-verb').html data.verb # tags.attr 'title', data.title # tags.removeClass( 'follow-toggle-on follow-toggle-off').addClass data.class # tags.data 'follow', data # } # event.preventDefault() # Prevent link from following its href # permissions mod $('body').on 'click', '.perm-vals input', -> $(this).slot().find('#inherit').attr('checked',false) $('body').on 'click', '.perm-editor #inherit', -> slot = $(this).slot() slot.find('.perm-group input:checked').attr('checked', false) slot.find('.perm-indiv input').val('') # rstar mod $('body').on 'click', '.rule-submit-button', -> f = $(this).closest('form') checked = f.find('.set-editor input:checked') if checked.val() if checked.attr('warning') confirm checked.attr('warning') else true else f.find('.set-editor').addClass('attention') $(this).notify 'To what Set does this Rule apply?' false # $('body').on 'click', '.rule-cancel-button', -> # $(this).closest('tr').find('.close-rule-link').click() $('body').on 'click', '.submit-modal', -> $(this).closest('.modal-content').find('form').submit() #wagn_org mod (for now) $('body').on 'click', '.shade-view h1', -> toggleThis = $(this).slot().find('.shade-content').is ':hidden' toggleShade $(this).closest('.pointer-list').find('.shade-content:visible').parent() if toggleThis toggleShade $(this).slot() if firstShade = $('.shade-view h1')[0] $(firstShade).trigger 'click' # following not in use?? $('body').on 'change', '.go-to-selected select', -> val = $(this).val() if val != '' window.location = wagn.rootPath + escape( val ) # performance log mod $('body').on 'click', '.open-slow-items', -> panel = $(this).closest('.panel-group') panel.find('.open-slow-items').removeClass('open-slow-items').addClass('close-slow-items') panel.find('.toggle-fast-items').text("show < 100ms") panel.find('.duration-ok').hide() panel.find('.panel-danger > .panel-collapse').collapse('show').find('a > span').addClass('show-fast-items') $('body').on 'click', '.close-slow-items', -> panel = $(this).closest('.panel-group') panel.find('.close-slow-items').removeClass('close-slow-items').addClass('open-slow-items') panel.find('.toggle-fast-items').text("hide < 100ms") panel.find('.panel-danger > .panel-collapse').collapse('hide').removeClass('show-fast-items') panel.find('.duration-ok').show() $('body').on 'click', '.toggle-fast-items', -> panel = $(this).closest('.panel-group') if $(this).text() == 'hide < 100ms' panel.find('.duration-ok').hide() $(this).text("show < 100ms") else panel.find('.duration-ok').show() $(this).text("hide < 100ms") $('body').on 'click', '.show-fast-items', (event) -> $(this).removeClass('show-fast-items') panel = $(this).closest('.panel-group') panel.find('.duration-ok').show() panel.find('.show-fast-items').removeClass('show-fast-items') panel.find('.panel-collapse').collapse('show') event.stopPropagation() toggleShade = (shadeSlot) -> shadeSlot.find('.shade-content').slideToggle 1000 shadeSlot.find('.glyphicon').toggleClass 'glyphicon-triangle-right glpyphicon-triangle-bottom' permissionsContent = (ed) -> return '_left' if ed.find('#inherit').is(':checked') groups = ed.find('.perm-group input:checked').map( -> $(this).val() ) indivs = ed.find('.perm-indiv input' ).map( -> $(this).val() ) pointerContent $.makeArray(groups).concat($.makeArray(indivs)) pointerContent = (vals) -> list = $.map $.makeArray(vals), (v)-> if v then '[[' + v + ']]' $.makeArray(list).join "\n" ace_editor_content = (element) -> ace_div = $(element).siblings(".ace_editor") editor = ace.edit(ace_div[0]) editor.getSession().getValue() #navbox mod reqIndex = 0 #prevents race conditions navbox_results = (request, response) -> f = this.element.closest 'form' formData = f.serialize() + '&view=complete' this.xhr = $.ajax { url: wagn.prepUrl wagn.rootPath + '/:search.json' data: formData dataType: "json" wagReq: ++reqIndex success: ( data, status ) -> response navboxize(request.term, data) if this.wagReq == reqIndex error: () -> response [] if this.wagReq == reqIndex } navboxize = (term, results)-> items = [] $.each ['search', 'add', 'new'], (index, key)-> if val = results[key] i = { value: term, prefix: key, icon: 'plus', label: '' + term + '' } if key == 'search' i.icon = key i.term = term else if key == 'add' i.href = '/card/new?card[name]=' + encodeURIComponent(val) else if key == 'new' i.type = 'add' # for icon i.href = '/new/' + val[1] items.push i $.each results['goto'], (index, val) -> items.push { icon: 'share-alt', prefix: 'go to', value: val[0], label: val[1], href: '/' + val[2] } $.each items, (index, i) -> i.label = '' + i.prefix + ': ' + '' + i.label + '' items navbox_select = (event, ui) -> if ui.item.term $(this).closest('form').submit() else window.location = wagn.rootPath + ui.item.href $(this).attr('disabled', 'disabled')