Skip to content

Instantly share code, notes, and snippets.

@kieranajp
Last active December 21, 2015 03:09
Show Gist options
  • Save kieranajp/6240244 to your computer and use it in GitHub Desktop.
Save kieranajp/6240244 to your computer and use it in GitHub Desktop.

News pages

Variables & functions

First things first, we're going to want to declare all our variables. We'll begin with caching some selectors so we can put them to good use later (we're going to use these guys a lot so we should keep them around here - beats parsing the DOM every time)

$head = $(".page-header")
$auth = $("#targeted_authority")
$focus = $("#targeted_focus")

I'd like to cache this one too if possible, but not sure I can due to its dynamic nature. Must experiment later. Not a huge deal as it's not used as frequently as the three above.

# $sub  = $("#targeted_sub")

We're using Ladda for the buttons on this site, at least for the look and feel. On some of the pages (mostly those with forms) we're actually using the Ladda functionality too, so if those buttons exist on the page that's been loaded we need to initialize them.

d = Ladda.create document.querySelector("#btn-archive") unless $("#btn-archive").length < 1
l = Ladda.create document.querySelector("[type=submit]") unless $("[type=submit]").length < 1

And let's drop our reusable functions at the top too (since JavaScript's weird function scoping will try to do this anyway).

This first function grabs a list of locations that are below the authority in hierarchy (LSS area, SLT area, whatever, it depends on the second parameter) and, if there are any returned from the server, spawns and populates a new drop down. It's not actually asynchronous, because we need this dropdown to be either spawned and fully populated or not at all, and being stuck in callback hell is dull.

focusAuthority = (authority, focus) ->
  $.ajax
    type     : "GET"
    url      : "/areas/#{authority}/#{focus}"
    dataType : "json"
    async    : false
    success  : (data) ->
      if data isnt false
        $("#targeted_sub").html("<option value='' disabled selected>Please select&hellip;</option>").show()

        for dt in data
          dt = dt.toLowerCase()
          $("#targeted_sub").append "<option value='#{dt}'>#{dt}</option>"

So here's probably the trickiest bit. This function has to select (possibly multiple) schools / whatevers in the #targeted_sub list. To accomplish this we're going to need an array of everything that should be selected in there, then we'll need to iterate through its values and match them up.

selectFocus = ->
  $.ajax
    type     : "GET"
    url      : "/areas/14" # this should be article id
    dataType : "json"
    success  : (data) ->
      if data.multiple is false
        $("#targeted_sub").val data.value.slice(0, -1)
      else
        values = data.value.split ";"

        $("#targeted_sub").val values

On Load

So, now for the stuff that happens on load. This script is loaded asynchronously, so no $ -> required - this stuff happens after ready anyway. We're using Bootstrap Datepicker plugin so let's kick that one off first.

$(".date").datepicker
  format : "yyyy-mm-dd" # Could make this friendlier at a later date

We're also using Redactor as our WYSIWYG editor.

$('.redactor').redactor
  imageUpload   : '/news/image/'
  convertDivs   : true
  buttons       : ['bold', 'italic', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'image', 'video', 'file', 'table', 'link', '|', 'fontcolor', '|', 'horizontalrule', '|', 'readmore']
  buttonsCustom :
    readmore    :
      title     : 'Read More'
      callback  : (obj) ->
        obj.execCommand 'inserthtml', '<!--readmore--> Read More<!--endreadmore-->';

In the interests of clarity we're going to actually declare an event here, amidst the onload stuff. There are some checkboxes on the form that flip open a panel when they're ticked.

$(".toggle").on "click", ->
  $(@).closest("div").children("div").slideToggle()

We're going to want to see if they're checked on load too so that they're flipped open then too. This'll prevent all sorts of weirdness.

$(".toggle").each ->
  $(@).closest("div").children("div").show() if $(@).attr "checked"

Finally let's pick the right values on page load, too, if this article is targeted.

if !!$auth.val()
  $focus.show()
  focusAuthority $auth.val(), $focus.val()
  if $focus.val() isnt ""
    selectFocus()

Events

Right, now for the events (bar the teeny one that snuck in above!)

These little guys make addional selects appear so you can narrow down your article targeting. Also, we make them disappear if applicable, too.

$auth.on "change", ->
  if $auth.val().length > 0
    $focus.show()
    $focus.val ""
    $("#targeted_sub").html("").hide()

$focus.on "change", ->
  v = $focus.val()
  if v.length > 0
    focusAuthority $auth.val(), v
  else
    $("#targeted_sub").html("").hide()

So on the pages this script is loaded on there are two ways of archiving articles. One is an archive button (or, more precisely, a load of archive buttons) with no going back from it - that makes life easy as we just have to send a DELETE request to the right URL ;)

$(".glyphicon-inbox").on "click", (e) ->
  e.preventDefault()
  $icon = $(@) # Hooray for function scoping

  $.ajax
    type     : "DELETE"
    url      : "/news/" + $icon.attr "data-archive"
    dataType : "json"
    success  : (data) ->
      $icon.replaceWith "<span class='label label-archived'>Archived</span>"

There's also a more complex means of archiving, where the button changes to essentially 'unarchive' if the article is archived. Simple enough, we can use the same URL (thanks to REST) but just change the request type depending on what button is displaying. These buttons are Ladda ones, by the way, so we need to deal with the spinniness too.

$("#btn-archive").on "click", (e) ->
  e.preventDefault()
  return if d.isLoading()
  d.start() # Start Ladda spinning

  $(".alert-activation").remove()

  color = $(@).attr "data-color"

  if color is "red"
    type = "DELETE"
  else
    type = "PUT"

  $.ajax
    type     : type
    url      : window.location.pathname
    dataType : "json"
    success  : (data) ->
      name = $(".page-header small").text()

      ### Could and totally should get this into its own function... there's reuse here ###

      window.setTimeout -> # Flip this guy on to let Ladda actually spin a bit ;)
        d.stop()

        if data.success is false
          $head.before "<div class='alert alert-danger'><strong>Error changing user status:</strong> An unexpected error occurred</div>"
        else if data.date is null
          $head.before "<div class='alert alert-activation'><strong>#{name}</strong> reactivated successfully!</div>"
          $('.label-archived').fadeOut()
          $('#btn-archive .ladda-label').text 'Archive'
          $('#btn-archive').attr 'data-color', 'red'
        else
          $head.before "<div class='alert alert-activation'><strong>#{name}</strong> archived successfully</div>"
          $('#btn-archive .ladda-label').text 'Restore'
          $('#btn-archive').attr 'data-color', 'green'
          $('.label-archived').fadeIn()
      , 1000

Finally we need to deal with what happens when someone hits save on an article. Easy peasy - again just firing a request of the right type to the right URL.

$(".news-article-form").on "submit", (e) ->
  e.preventDefault()

  return if l.isLoading()
  return if not $(@).parsley "validate"

  $(".alert").remove()
  l.start()

  $.ajax
    type     : "POST"
    url      : window.location.pathname
    data     : $(@).serialize()
    dataType : "json"
    success  : (data) ->
      if not data.success
        message = "An error occurred when saving"
        type = "danger"
      else
        message = "Changes saved successfully!"
        type = "success"

      window.setTimeout ->
        l.stop()
        $head.after "<div class='alert alert-#{type}'>#{message}</div>"

        h1 = $(".page-header h1").text().trim().toLowerCase().substring 0, 3
        if h1 is "new"
          $("input, textarea, select, [type=submit]").attr "disabled", "disabled"
          $("[type=submit]").hide().after "<a class='btn ladda-button' data-color='green' href='/news/'>View Article List</a>"
      , 1000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment