<commit_before>/*
 * Copyright 2012 Amadeus s.a.s.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var asyncRequire = require('noder-js/asyncRequire').create(module);
var promise = require('noder-js/promise');

var errorsList = {
    "XMLHttpRequest": function(out, url, xhr) {
        out.unshift("failed to download '", url, "': ", xhr.status, " ", xhr.statusText, "\n");
        return promise.done;
    },
    "moduleLoadDefinition": function(out, module) {
        out.unshift("failed to load definition of module '", module.filename, "'\n");
        return unshiftErrorInfo(this.cause, out);
    },
    "moduleProcessPlugin": function(out, module, pluginDef) {
        out.unshift("failed to process plugin require('", pluginDef.module, "')." + pluginDef.method + " for module '", module.filename, "'\n");
        return unshiftErrorInfo(this.cause, out);
    },
    "modulePreload": function(out, module) {
        if (module.filename != '.') {
            out.unshift("failed to preload '", module.filename, "'\n");
        }
        return unshiftErrorInfo(this.cause, out);
    },
    "modulePreloadRec": function(out, module) {
        if (module.filename != '.') {
            out.unshift("invalid recursive call to modulePreload '", module.filename, "'\n");
        }
        return promise.done;
    },
    "notPreloaded": function(out, module) {
        out.unshift("cannot execute module '", module.filename, "' as it is not preloaded.\n");
        return promise.done;
    },
    "jsEval": function(out, jsCode, url, lineDiff) {
        return asyncRequire(['./evalError.js']).thenSync(function() {
            var evalError = asyncRequire('./evalError.js');
            var syntaxError = evalError(out, jsCode, url, lineDiff);
            if (!syntaxError) {
                out.unshift("error while evaluating '" + url + "'\n");
                return unshiftErrorInfo(this.cause, out);
            }
        });
    },
    "resolverRoot": function(out, path) {
        out.unshift("trying to go upper than the root of modules when resolving '", path.join('/'), "'\n");
        return promise.done;
    },
    "resolverLoop": function(out, path) {
        out.unshift("inifinite loop when resolving '", path.join('/'), "'\n");
        return promise.done;
    }
};

var unshiftErrorInfo = function(error, out) {
    if (error && error.name == "NoderError") {
        var code = error.code;
        var handler = errorsList[code];
        if (handler) {
            var params = [out].concat(error.args || []);
            return handler.apply(error, params);
        }
    } else {
        out.unshift(error + "\n");
    }
    return promise.done;
};

module.exports = function(async) {
    var self = this;
    var out = [];
    var res = unshiftErrorInfo(self, out).thenSync(function() {
        var message = out.join('');
        self.message = self.description = message;
        if (async) {
            console.error("Details about NoderError #" + self.id + ":\n" + message);
        }
    });
    async = true;
    return res;
};
<commit_msg>Fixing an issue after changing the API of asyncRequest.<commit_after>/*
 * Copyright 2012 Amadeus s.a.s.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var asyncRequire = require('noder-js/asyncRequire').create(module);
var promise = require('noder-js/promise');

var errorsList = {
    "XMLHttpRequest": function(out, url, xhr) {
        out.unshift("failed to download '", url, "': ", xhr.status, " ", xhr.statusText, "\n");
        return promise.done;
    },
    "moduleLoadDefinition": function(out, module) {
        out.unshift("failed to load definition of module '", module.filename, "'\n");
        return unshiftErrorInfo(this.cause, out);
    },
    "moduleProcessPlugin": function(out, module, pluginDef) {
        out.unshift("failed to process plugin require('", pluginDef.module, "')." + pluginDef.method + " for module '", module.filename, "'\n");
        return unshiftErrorInfo(this.cause, out);
    },
    "modulePreload": function(out, module) {
        if (module.filename != '.') {
            out.unshift("failed to preload '", module.filename, "'\n");
        }
        return unshiftErrorInfo(this.cause, out);
    },
    "modulePreloadRec": function(out, module) {
        if (module.filename != '.') {
            out.unshift("invalid recursive call to modulePreload '", module.filename, "'\n");
        }
        return promise.done;
    },
    "notPreloaded": function(out, module) {
        out.unshift("cannot execute module '", module.filename, "' as it is not preloaded.\n");
        return promise.done;
    },
    "jsEval": function(out, jsCode, url, lineDiff) {
        return asyncRequire('./evalError.js').thenSync(function(evalError) {
            var syntaxError = evalError(out, jsCode, url, lineDiff);
            if (!syntaxError) {
                out.unshift("error while evaluating '" + url + "'\n");
                return unshiftErrorInfo(this.cause, out);
            }
        });
    },
    "resolverRoot": function(out, path) {
        out.unshift("trying to go upper than the root of modules when resolving '", path.join('/'), "'\n");
        return promise.done;
    },
    "resolverLoop": function(out, path) {
        out.unshift("inifinite loop when resolving '", path.join('/'), "'\n");
        return promise.done;
    }
};

var unshiftErrorInfo = function(error, out) {
    if (error && error.name == "NoderError") {
        var code = error.code;
        var handler = errorsList[code];
        if (handler) {
            var params = [out].concat(error.args || []);
            return handler.apply(error, params);
        }
    } else {
        out.unshift(error + "\n");
    }
    return promise.done;
};

module.exports = function(async) {
    var self = this;
    var out = [];
    var res = unshiftErrorInfo(self, out).thenSync(function() {
        var message = out.join('');
        self.message = self.description = message;
        if (async) {
            console.error("Details about NoderError #" + self.id + ":\n" + message);
        }
    });
    async = true;
    return res;
};
<|endoftext|>


<commit_before>(function ($) {
  // register namespace
  $.extend(true, window, {
    "Slick": {
      "Plugins": {
        "HeaderMenu": HeaderMenu
      }
    }
  });

  /***
   * A plugin to add drop-down menus to column headers.
   *
   * USAGE:
   *
   * Add the plugin .js & .css files and register it with the grid.
   *
   * To specify a menu in a column header, extend the column definition like so:
   *
   *   var columns = [
   *     {
   *       id: 'myColumn',
   *       name: 'My column',
   *
   *       // This is the relevant part
   *       header: {
   *          menu: {
   *              items: [
   *                {
   *                  // menu item options
   *                },
   *                {
   *                  // menu item options
   *                }
   *              ]
   *          }
   *       }
   *     }
   *   ];
   *
   *
   * Available menu options:
   *    tooltip:      Menu button tooltip.
   *
   *
   * Available menu item options:
   *    title:        Menu item text.
   *    disabled:     Whether the item is disabled.
   *    tooltip:      Item tooltip.
   *    command:      A command identifier to be passed to the onCommand event handlers.
   *    iconCssClass: A CSS class to be added to the menu item icon.
   *    iconImage:    A url to the icon image.
   *
   *
   * The plugin exposes the following events:
   *    onBeforeMenuShow:   Fired before the menu is shown.  You can customize the menu or dismiss it by returning false.
   *        Event args:
   *            grid:     Reference to the grid.
   *            column:   Column definition.
   *            menu:     Menu options.  Note that you can change the menu items here.
   *
   *    onCommand:    Fired on menu item click for buttons with 'command' specified.
   *        Event args:
   *            grid:     Reference to the grid.
   *            column:   Column definition.
   *            command:  Button command identified.
   *            button:   Button options.  Note that you can change the button options in your
   *                      event handler, and the column header will be automatically updated to
   *                      reflect them.  This is useful if you want to implement something like a
   *                      toggle button.
   *
   *
   * @param options {Object} Options:
   *    buttonCssClass:   an extra CSS class to add to the menu button
   *    buttonImage:      a url to the menu button image (default '../images/down.gif')
   * @class Slick.Plugins.HeaderButtons
   * @constructor
   */
  function HeaderMenu(options) {
    var _grid;
    var _self = this;
    var _handler = new Slick.EventHandler();
    var _defaults = {
      buttonCssClass: null,
      buttonImage: null
    };
    var $menu;
    var $activeHeaderColumn;

    function init(grid) {
      options = $.extend(true, {}, _defaults, options);
      _grid = grid;
      _handler
        .subscribe(_grid.onHeaderCellRendered, handleHeaderCellRendered)
        .subscribe(_grid.onBeforeHeaderCellDestroy, handleBeforeHeaderCellDestroy);

      // Force the grid to re-render the header now that the events are hooked up.
      _grid.setColumns(_grid.getColumns());

      // Hide the menu on outside click.
      $(document.body).bind("mousedown", handleBodyMouseDown);
    }

    function destroy() {
      _handler.unsubscribeAll();
      $(document.body).unbind("mousedown", handleBodyMouseDown);
    }

    function handleBodyMouseDown(e) {
      if ($menu && $menu[0] != e.target && !$.contains($menu[0], e.target)) {
        hideMenu();
      }
    }

    function hideMenu() {
      if ($menu) {
        $menu.remove();
        $menu = null;
        $activeHeaderColumn
          .removeClass("slick-header-column-active");
      }
    }

    function handleHeaderCellRendered(e, args) {
      var column = args.column;
      var menu = column.header && column.header.menu;

      if (menu) {
        var $el = $("

")
          .addClass("slick-header-menubutton")
          .data("column", column)
          .data("menu", menu);

        if (options.buttonCssClass) {
          $el.addClass(options.buttonCssClass);
        }

        if (options.buttonImage) {
          $el.css("background-image", "url(" + options.buttonImage + ")");
        }

        if (menu.tooltip) {
          $el.attr("title", menu.tooltip);
        }

        $el
          .bind("click", showMenu)
          .appendTo(args.node);
      }
    }

    function handleBeforeHeaderCellDestroy(e, args) {
      var column = args.column;

      if (column.header && column.header.menu) {
        $(args.node).find(".slick-header-menubutton").remove();
      }
    }

    function showMenu(e) {
      var $menuButton = $(this);
      var menu = $menuButton.data("menu");
      var columnDef = $menuButton.data("column");

      // Let the user modify the menu or cancel altogether,
      // or provide alternative menu implementation.
      if (_self.onBeforeMenuShow.notify({
          "grid": _grid,
          "column": columnDef,
          "menu": menu
        }, e, _self) == false) {
        return;
      }

      if (!$menu) {
        $menu = $("

")
          .appendTo(_grid.getContainerNode());
      }
      $menu.empty();

      // Construct the menu items.
      for (var i = 0; i < menu.items.length; i++) {
        var item = menu.items[i];

        var $li = $("

")
          .data("command", item.command || '')
          .data("column", columnDef)
          .data("item", item)
          .bind("click", handleMenuItemClick)
          .appendTo($menu);

        if (item.disabled) {
          $li.addClass("slick-header-menuitem-disabled");
        }

        if (item.tooltip) {
          $li.attr("title", item.tooltip);
        }

        var $icon = $("

")
          .appendTo($li);

        if (item.iconCssClass) {
          $icon.addClass(item.iconCssClass);
        }

        if (item.iconImage) {
          $icon.css("background-image", "url(" + item.iconImage + ")");
        }

        $("")
          .text(item.title)
          .appendTo($li);
      }

      // Position the menu.
      $menu
        .offset({ top: $(this).offset().top + $(this).height(), left: $(this).offset().left });

      // Mark the header as active to keep the highlighting.
      $activeHeaderColumn = $menuButton.closest(".slick-header-column");
      $activeHeaderColumn
        .addClass("slick-header-column-active");

      // Stop propagation so that it doesn't register as a header click event.
      e.preventDefault();
      e.stopPropagation();
    }

    function handleMenuItemClick(e) {
      var command = $(this).data("command");
      var columnDef = $(this).data("column");
      var item = $(this).data("item");

      if (item.disabled) {
        return;
      }

      hideMenu();

      if (command != null && command != '') {
        _self.onCommand.notify({
            "grid": _grid,
            "column": columnDef,
            "command": command,
            "item": item
          }, e, _self);
      }

      // Stop propagation so that it doesn't register as a header click event.
      e.preventDefault();
      e.stopPropagation();
    }

    $.extend(this, {
      "init": init,
      "destroy": destroy,

      "onBeforeMenuShow": new Slick.Event(),
      "onCommand": new Slick.Event()
    });
  }
})(jQuery);
<commit_msg>Delete slick.headermenu.js<commit_after><|endoftext|>


<commit_before>var SurveillanceCenter = {

  CSS_TRIGGER_REFRESH_LIVEVIEW: '.js-refresh-liveview',
  CSS_TRIGGER_CAMERA_FALLBACK: '.js-camera-fallback',
  CSS_TRIGGER_PUSH_NOTIFICATION_SETTINGS_TOGGLE: '.js-push-notification-settings-toggle',
  CSS_TRIGGER_ARCHIVE_RECORDINGS_SETTINGS_CLICK: '.js-archive-recordings-settings-click',
  CSS_PUSH_NOTIFICATION_SETTINGS_ERROR: '#js-push-notification-settings-error',
  CSS_SETTINGS_ENDPOINT_CONFIGURATION: '#settings-endpoint-configuration',
  CSS_ARCHIVE_RECORDINGS_SETTINGS_RESULT_SUCCESS: '#js-archive-recordings-settings-result-success',
  CSS_ARCHIVE_RECORDINGS_SETTINGS_RESULT_ERROR: '#js-archive-recordings-settings-result-error',
  CSS_NOTIFIER_CONFIGURATION: '#notifier-configuration',
  CSS_NOTIFIER_BADGE: '#js-notifier-badge',
  CSS_LIVEVIEW_CONTAINER: '#liveview-container',
  CSS_LIVEVIEW_CONTAINER_LOADER: '#liveview-container-loader',
  LIVEVIEW_CONTAINER_ID: 'liveview-container',
  LIVEVIEW_CONTAINER_LOADER_ID: 'liveview-container-loader',

  /**
   * Initialize all listeners.
   */
  init: function() {
    this.addRefreshLiveviewListener();
    this.addRotationListener();
    this.addCameraFallbackImagesListener();
    this.addPushNotificationSettingsToggleListener();
    this.addArchiveRecordingsSettingsListener();
    this.addNotifier();
  },

  /**
   * Refresh liveview image on click.
   */
  addRefreshLiveviewListener: function() {
    var that = this;
    $(this.CSS_TRIGGER_REFRESH_LIVEVIEW).on('click', function() {
      var button = this;
      $(button).addClass('active');
      $(button).prop('disabled', true);
      $.ajax({
        url: $(this).data('url')
      }).done(function(data) {
        // load result in hidden container
        $(that.CSS_LIVEVIEW_CONTAINER_LOADER).append(data);
        that.addCameraFallbackImagesListener();
        // wait for image(s) to be loaded
        $(that.CSS_LIVEVIEW_CONTAINER_LOADER).imagesLoaded(function() {
          // move content to visible container
          $(that.CSS_LIVEVIEW_CONTAINER).replaceWith($(that.CSS_LIVEVIEW_CONTAINER_LOADER));
          $(that.CSS_LIVEVIEW_CONTAINER_LOADER).attr('id', that.LIVEVIEW_CONTAINER_ID);
          $(that.CSS_LIVEVIEW_CONTAINER).removeClass('hidden');
          // create a new hidden loader container for next request
          $(that.CSS_LIVEVIEW_CONTAINER).after($('<div/>').attr('id', that.LIVEVIEW_CONTAINER_LOADER_ID).addClass('hidden'));
          // rotate image if necessary
          that.rotateImages();
          // activate refresh button again
          $(button).prop('disabled', false);
          $(button).removeClass('active');
        });
      });
    });
  },

  /**
   * Add camera fallback images listener.
   * Will show a default image for cameras that are offline.
   */
  addCameraFallbackImagesListener: function() {
    $(this.CSS_TRIGGER_CAMERA_FALLBACK).on('error', function() {
      console.log('Camera ' + $(this).attr('src') + ' seems to be offline.');
      $(this).off();
      var contextPath = window.location.pathname.substring(0, window.location.pathname.indexOf("/liveview"));
      $(this).attr('src', contextPath + '/img/camera-offline.svg');
    });
  },

  /**
   * Add listener for push notification toggle buttons on settings page.
   */
  addPushNotificationSettingsToggleListener: function() {
    var that = this;
    $(this.CSS_TRIGGER_PUSH_NOTIFICATION_SETTINGS_TOGGLE).on('click', function() {
      var endpoint = $(that.CSS_SETTINGS_ENDPOINT_CONFIGURATION).data('push-notification-settings-endpoint');
      var cameraId = $(this).data('camera-id');
      var currentEnabledStatus = $(this).data('enabled-status');
      var newEnabledStatus = !currentEnabledStatus;
      var data = {
    	'enabled': newEnabledStatus
      };
      var button = this;
      $.ajax({
        url: endpoint + cameraId,
        method: 'PUT',
        contentType: 'application/json; charset=UTF-8',
        dataType: 'json',
        data: JSON.stringify(data)
      }).done(function(data) {
        $(button).data('enabled-status', newEnabledStatus);
        $(button).find('.btn').toggleClass('active');
        $(button).find('.btn').toggleClass('btn-primary');
        $(button).find('.btn').toggleClass('btn-default');
      }).fail(function(data) {
        $(that.CSS_PUSH_NOTIFICATION_SETTINGS_ERROR).collapse('show');
      });
    });
  },

  /**
   * Add listener to archive all recordings button on settings page.
   */
  addArchiveRecordingsSettingsListener: function() {
    var that = this;

    $(this.CSS_TRIGGER_ARCHIVE_RECORDINGS_SETTINGS_CLICK).on('click', function() {
      var endpoint = $(that.CSS_SETTINGS_ENDPOINT_CONFIGURATION).data('archive-recordings-settings-endpoint');
      var data = {
        'archived': true
      };

      $.ajax({
        url: endpoint,
        method: 'POST',
        contentType: 'application/json; charset=UTF-8',
        dataType: 'json',
        data: JSON.stringify(data)
      }).done(function() {
        $(that.CSS_ARCHIVE_RECORDINGS_SETTINGS_RESULT_SUCCESS).collapse('show');
      }).fail(function() {
        $(that.CSS_ARCHIVE_RECORDINGS_SETTINGS_RESULT_ERROR).collapse('show');
      });
    });
  },

  /**
   * Add notifier, showing number of recordings in window title and as headline badge.
   */
  addNotifier: function() {
    var enabled = $(this.CSS_NOTIFIER_CONFIGURATION).data('notifier-enabled');
    if (enabled) {
      var endpoint = $(this.CSS_NOTIFIER_CONFIGURATION).data('notifier-endpoint');
      var interval = $(this.CSS_NOTIFIER_CONFIGURATION).data('notifier-interval') * 1000;
      var that = this;

      (function pollApi() {
        $.getJSON(endpoint, function(data) {
          var count = data.count;
          var currentTitle = $(document).attr('title');
          var pattern = /\(\d+\)/;

          // remove, replace or append count value
          if (count === 0) {
            $(that.CSS_NOTIFIER_BADGE).text('');
            $(document).attr('title', currentTitle.replace(pattern, ''));
          } else {
            $(that.CSS_NOTIFIER_BADGE).text(count);
            if (pattern.exec(currentTitle)) {
              $(document).attr('title', currentTitle.replace(pattern, '(' + count + ')'));
            } else {
              $(document).attr('title', currentTitle + ' (' + count + ')');
            }
          }
          setTimeout(pollApi, interval);
        });
      }());
    }
  },

  /**
   * Listener to invoke image rotation.
   */
  addRotationListener: function() {
    if ($('[data-rotate]').length == 0) {
      return;
    }

    var that = this;
    this.rotateImages();
    $(window).resize(function() {
      that.rotateImages();
    });
  },

  /**
   * Rotate images.
   * @private
   */
  rotateImages: function() {
    $('[data-rotate]').each(function() {
      var rotateValue = $(this).data('rotate');

      if (rotateValue > 0) {
        $(this).css({
          '-webkit-transform': 'rotate(' + rotateValue + 'deg)',
          'transform': 'rotate(' + rotateValue + 'deg)',
          'height': $(this).parent().width() + 'px',
          'width': 'auto'
        });
      }
    });
  }

};

/**
 * Initialize SurveillanceCenter on dom ready.
 */
$(document).ready(function() {
  SurveillanceCenter.init();
});
<commit_msg>Reset notifier after archiving all images<commit_after>var SurveillanceCenter = {

  CSS_TRIGGER_REFRESH_LIVEVIEW: '.js-refresh-liveview',
  CSS_TRIGGER_CAMERA_FALLBACK: '.js-camera-fallback',
  CSS_TRIGGER_PUSH_NOTIFICATION_SETTINGS_TOGGLE: '.js-push-notification-settings-toggle',
  CSS_TRIGGER_ARCHIVE_RECORDINGS_SETTINGS_CLICK: '.js-archive-recordings-settings-click',
  CSS_PUSH_NOTIFICATION_SETTINGS_ERROR: '#js-push-notification-settings-error',
  CSS_SETTINGS_ENDPOINT_CONFIGURATION: '#settings-endpoint-configuration',
  CSS_ARCHIVE_RECORDINGS_SETTINGS_RESULT_SUCCESS: '#js-archive-recordings-settings-result-success',
  CSS_ARCHIVE_RECORDINGS_SETTINGS_RESULT_ERROR: '#js-archive-recordings-settings-result-error',
  CSS_NOTIFIER_CONFIGURATION: '#notifier-configuration',
  CSS_NOTIFIER_BADGE: '#js-notifier-badge',
  CSS_LIVEVIEW_CONTAINER: '#liveview-container',
  CSS_LIVEVIEW_CONTAINER_LOADER: '#liveview-container-loader',
  LIVEVIEW_CONTAINER_ID: 'liveview-container',
  LIVEVIEW_CONTAINER_LOADER_ID: 'liveview-container-loader',
  NOTIFIER_TITLE_PATTERN: /\(\d+\)/,

  /**
   * Initialize all listeners.
   */
  init: function() {
    this.addRefreshLiveviewListener();
    this.addRotationListener();
    this.addCameraFallbackImagesListener();
    this.addPushNotificationSettingsToggleListener();
    this.addArchiveRecordingsSettingsListener();
    this.addNotifier();
  },

  /**
   * Refresh liveview image on click.
   */
  addRefreshLiveviewListener: function() {
    var that = this;
    $(this.CSS_TRIGGER_REFRESH_LIVEVIEW).on('click', function() {
      var button = this;
      $(button).addClass('active');
      $(button).prop('disabled', true);
      $.ajax({
        url: $(this).data('url')
      }).done(function(data) {
        // load result in hidden container
        $(that.CSS_LIVEVIEW_CONTAINER_LOADER).append(data);
        that.addCameraFallbackImagesListener();
        // wait for image(s) to be loaded
        $(that.CSS_LIVEVIEW_CONTAINER_LOADER).imagesLoaded(function() {
          // move content to visible container
          $(that.CSS_LIVEVIEW_CONTAINER).replaceWith($(that.CSS_LIVEVIEW_CONTAINER_LOADER));
          $(that.CSS_LIVEVIEW_CONTAINER_LOADER).attr('id', that.LIVEVIEW_CONTAINER_ID);
          $(that.CSS_LIVEVIEW_CONTAINER).removeClass('hidden');
          // create a new hidden loader container for next request
          $(that.CSS_LIVEVIEW_CONTAINER).after($('<div/>').attr('id', that.LIVEVIEW_CONTAINER_LOADER_ID).addClass('hidden'));
          // rotate image if necessary
          that.rotateImages();
          // activate refresh button again
          $(button).prop('disabled', false);
          $(button).removeClass('active');
        });
      });
    });
  },

  /**
   * Add camera fallback images listener.
   * Will show a default image for cameras that are offline.
   */
  addCameraFallbackImagesListener: function() {
    $(this.CSS_TRIGGER_CAMERA_FALLBACK).on('error', function() {
      console.log('Camera ' + $(this).attr('src') + ' seems to be offline.');
      $(this).off();
      var contextPath = window.location.pathname.substring(0, window.location.pathname.indexOf("/liveview"));
      $(this).attr('src', contextPath + '/img/camera-offline.svg');
    });
  },

  /**
   * Add listener for push notification toggle buttons on settings page.
   */
  addPushNotificationSettingsToggleListener: function() {
    var that = this;
    $(this.CSS_TRIGGER_PUSH_NOTIFICATION_SETTINGS_TOGGLE).on('click', function() {
      var endpoint = $(that.CSS_SETTINGS_ENDPOINT_CONFIGURATION).data('push-notification-settings-endpoint');
      var cameraId = $(this).data('camera-id');
      var currentEnabledStatus = $(this).data('enabled-status');
      var newEnabledStatus = !currentEnabledStatus;
      var data = {
    	'enabled': newEnabledStatus
      };
      var button = this;
      $.ajax({
        url: endpoint + cameraId,
        method: 'PUT',
        contentType: 'application/json; charset=UTF-8',
        dataType: 'json',
        data: JSON.stringify(data)
      }).done(function(data) {
        $(button).data('enabled-status', newEnabledStatus);
        $(button).find('.btn').toggleClass('active');
        $(button).find('.btn').toggleClass('btn-primary');
        $(button).find('.btn').toggleClass('btn-default');
      }).fail(function(data) {
        $(that.CSS_PUSH_NOTIFICATION_SETTINGS_ERROR).collapse('show');
      });
    });
  },

  /**
   * Add listener to archive all recordings button on settings page.
   */
  addArchiveRecordingsSettingsListener: function() {
    var that = this;

    $(this.CSS_TRIGGER_ARCHIVE_RECORDINGS_SETTINGS_CLICK).on('click', function() {
      var endpoint = $(that.CSS_SETTINGS_ENDPOINT_CONFIGURATION).data('archive-recordings-settings-endpoint');
      var data = {
        'archived': true
      };

      $.ajax({
        url: endpoint,
        method: 'POST',
        contentType: 'application/json; charset=UTF-8',
        dataType: 'json',
        data: JSON.stringify(data)
      }).done(function() {
        $(that.CSS_ARCHIVE_RECORDINGS_SETTINGS_RESULT_SUCCESS).collapse('show');
        that.resetNotifier();
      }).fail(function() {
        $(that.CSS_ARCHIVE_RECORDINGS_SETTINGS_RESULT_ERROR).collapse('show');
      });
    });
  },

  /**
   * Add notifier, showing number of recordings in window title and as headline badge.
   */
  addNotifier: function() {
    var enabled = $(this.CSS_NOTIFIER_CONFIGURATION).data('notifier-enabled');
    if (enabled) {
      var endpoint = $(this.CSS_NOTIFIER_CONFIGURATION).data('notifier-endpoint');
      var interval = $(this.CSS_NOTIFIER_CONFIGURATION).data('notifier-interval') * 1000;
      var that = this;

      (function pollApi() {
        $.getJSON(endpoint, function(data) {
          var count = data.count;
          var pattern = that.NOTIFIER_TITLE_PATTERN;
          var currentTitle = $(document).attr('title');

          // remove, replace or append count value
          if (count === 0) {
            that.resetNotifier();
          } else {
            $(that.CSS_NOTIFIER_BADGE).text(count);
            if (pattern.exec(currentTitle)) {
              $(document).attr('title', currentTitle.replace(pattern, '(' + count + ')'));
            } else {
              $(document).attr('title', currentTitle + ' (' + count + ')');
            }
          }
          setTimeout(pollApi, interval);
        });
      }());
    }
  },

  /**
   * Listener to invoke image rotation.
   */
  addRotationListener: function() {
    if ($('[data-rotate]').length == 0) {
      return;
    }

    var that = this;
    this.rotateImages();
    $(window).resize(function() {
      that.rotateImages();
    });
  },

  /**
   * Adjust notifier value to zero. Document title and notification badge.
   * @private
   */
  resetNotifier: function() {
    var currentTitle = $(document).attr('title');
    $(this.CSS_NOTIFIER_BADGE).text('');
    $(document).attr('title', currentTitle.replace(this.NOTIFIER_TITLE_PATTERN, ''));
  },

  /**
   * Rotate images.
   * @private
   */
  rotateImages: function() {
    $('[data-rotate]').each(function() {
      var rotateValue = $(this).data('rotate');

      if (rotateValue > 0) {
        $(this).css({
          '-webkit-transform': 'rotate(' + rotateValue + 'deg)',
          'transform': 'rotate(' + rotateValue + 'deg)',
          'height': $(this).parent().width() + 'px',
          'width': 'auto'
        });
      }
    });
  }

};

/**
 * Initialize SurveillanceCenter on dom ready.
 */
$(document).ready(function() {
  SurveillanceCenter.init();
});
<|endoftext|>


<commit_before>/*
Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
For licensing, see license.txt or http://cksource.com/ckfinder/license
*/

CKFinder.customConfig = function( config )
{
	// Define changes to default configuration here.
	// For the list of available options, check:
	// http://docs.cksource.com/ckfinder_2.x_api/symbols/CKFinder.config.html

	// Sample configuration options:
	// config.uiColor = '#BDE31E';
	// config.language = 'fr';
	// config.removePlugins = 'basket';

};
<commit_msg>Remove help button<commit_after>/*
Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
For licensing, see license.txt or http://cksource.com/ckfinder/license
*/

CKFinder.customConfig = function( config )
{
	// Define changes to default configuration here.
	// For the list of available options, check:
	// http://docs.cksource.com/ckfinder_2.x_api/symbols/CKFinder.config.html

	// Sample configuration options:
	// config.uiColor = '#BDE31E';
	// config.language = 'fr';
	config.removePlugins = 'help';

};
<|endoftext|>


<commit_before>const HOURS_PER_DAY = 24;
const MINUTES_PER_HOUR = 60;
const SECONDS_PER_MINUTE = 60;
const SECONDS_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE;
const MILLISECONDS_PER_SECOND = 1000;

/**
 * Get the value of a cookie.
 */
function getCookie(name) {
  let decodedCookie = decodeURIComponent(document.cookie);
  let cookies = decodedCookie.split(';');
  for (let i = 0; i < cookies.length; i++) {
    cookieParts = cookies[i].trim().split("=");
    if (cookieParts[0] === name) {
      return cookieParts[1];
    }
  }
  return "";
}

/**
 * Create a new cookie based on name, value and days before expiring.
 */
function setCookie(name, value, expirationDays) {
  let date = new Date();
  date.setTime(date.getTime + expirationDays * SECONDS_PER_DAY * MILLISECONDS_PER_SECOND);
  document.cookie = `${name}=${value};expires=${expirationDays}`;
}

/**
 * Set the cookie value of a change event.
 */
function setChangeCookie(event) {
  let name = event.currentTarget.id;
  let value = event.currentTarget.value;
  setCookie(name, value, 1);
}

/**
 * Set the cookie value of a checkbox click event.
 */
function setCheckboxCookie(event) {
  let name = event.currentTarget.id;
  let value = event.currentTarget.checked;
  setCookie(name, value, 1);
}

/**
 * Erase a cookie based on name.
 */
function eraseCookie(name) {
  document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
}

/**
 * Load the cookie value of a select element to the DOM.
 */
function loadSelectValueCookie(cookieName) {
  cookieValue = getCookie(cookieName);
  if (cookieValue !== "") {
      document.getElementById(`${cookieValue}-option`).selected = "selected";
  }
}

/**
 * Load the cookie value of a numeric input element to the DOM.
 */
function loadNumericValueCookie(cookieName) {
  cookieValue = getCookie(cookieName);
  if (cookieValue !== "") {
      document.getElementById(cookieName).value = cookieValue;
  }
}

/**
 * Load the cookie state of a checkbox input element to the DOM.
 */
function loadCheckboxStateCookie(cookieName) {
  cookieValue = getCookie(cookieName);
  if (cookieValue !== "") {
      document.getElementById(cookieName).checked = (cookieValue === "true");
  }
}

/**
 * Makes cookies for the user's latitude and longitude coordinates.
 */
function setLocationCookie() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
        setCookie("latitude", position.coords.latitude, 1);
        setCookie("longitude", position.coords.longitude, 1);
      }, function(err) {
        console.warn(`ERROR(${err.code}): ${err.message}`);
        alert("We cannot access your location. Try checking your browswer settings");
      })
    };
}
<commit_msg>Remove position cookie<commit_after>const HOURS_PER_DAY = 24;
const MINUTES_PER_HOUR = 60;
const SECONDS_PER_MINUTE = 60;
const SECONDS_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE;
const MILLISECONDS_PER_SECOND = 1000;

/**
 * Get the value of a cookie.
 */
function getCookie(name) {
  let decodedCookie = decodeURIComponent(document.cookie);
  let cookies = decodedCookie.split(';');
  for (let i = 0; i < cookies.length; i++) {
    cookieParts = cookies[i].trim().split("=");
    if (cookieParts[0] === name) {
      return cookieParts[1];
    }
  }
  return "";
}

/**
 * Create a new cookie based on name, value and days before expiring.
 */
function setCookie(name, value, expirationDays) {
  let date = new Date();
  date.setTime(date.getTime + expirationDays * SECONDS_PER_DAY * MILLISECONDS_PER_SECOND);
  document.cookie = `${name}=${value};expires=${expirationDays}`;
}

/**
 * Set the cookie value of a change event.
 */
function setChangeCookie(event) {
  let name = event.currentTarget.id;
  let value = event.currentTarget.value;
  setCookie(name, value, 1);
}

/**
 * Set the cookie value of a checkbox click event.
 */
function setCheckboxCookie(event) {
  let name = event.currentTarget.id;
  let value = event.currentTarget.checked;
  setCookie(name, value, 1);
}

/**
 * Erase a cookie based on name.
 */
function eraseCookie(name) {
  document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
}

/**
 * Load the cookie value of a select element to the DOM.
 */
function loadSelectValueCookie(cookieName) {
  cookieValue = getCookie(cookieName);
  if (cookieValue !== "") {
      document.getElementById(`${cookieValue}-option`).selected = "selected";
  }
}

/**
 * Load the cookie value of a numeric input element to the DOM.
 */
function loadNumericValueCookie(cookieName) {
  cookieValue = getCookie(cookieName);
  if (cookieValue !== "") {
      document.getElementById(cookieName).value = cookieValue;
  }
}

/**
 * Load the cookie state of a checkbox input element to the DOM.
 */
function loadCheckboxStateCookie(cookieName) {
  cookieValue = getCookie(cookieName);
  if (cookieValue !== "") {
      document.getElementById(cookieName).checked = (cookieValue === "true");
  }
}
<|endoftext|>


<commit_before>"use strict";

$(function() {

    function reorderIssues(li, val, callback) {
        $('#agenda-container').addClass('loading');
        var l = $('#agenda li').map(function() {
            return $(this).data('issue');
        }).get();
        $.post('', {
            issues : l,
        }, function(data) {
            $('#agenda-container').removeClass('loading');
        }).fail(function() {
            alert('Server Error. Please refresh your browser and try again');
        });
    }

    function toggleIssue(li, val, callback) {
        $.post('', {
            issue : li.data('issue'),
            set : val
        }, function(data) {
            li.removeClass('loading');
        }).fail(function() {
            alert('Server Error. Please refresh your browser and try again');
        });
    }

    $('#agenda').on('click', '.addremove', function() {
        $(this).find('.ui-icon-minus').removeClass('ui-icon-minus').addClass('ui-icon-plus');
        var el = $(this).parent();
        el.addClass('loading');
        $("#available").append(el);
        toggleIssue(el, 1);
    }).sortable({
        'containment': $('#agenda').parent().parent(),
        'forcePlaceholderSize': true,
        'opacity': 0.6,
        update: function(event, ui) {
            reorderIssues();
        }
    }).removeClass('ui-corner-all').filter('li').removeClass('ui-corner-bottom');

    $('#available').on('click', '.addremove', function() {
        $(this).find('.ui-icon-plus').removeClass('ui-icon-plus').addClass('ui-icon-minus');
        var el = $(this).parent();
        el.addClass('loading');
        $("#agenda").append(el);
        toggleIssue(el, 0);
    });

});
<commit_msg>small fix to sortable agenda (3rd  try)<commit_after>"use strict";

$(function() {

    function reorderIssues(li, val, callback) {
        $('#agenda-container').addClass('loading');
        var l = $('#agenda li').map(function() {
            return $(this).data('issue');
        }).get();
        $.post('', {
            issues : l,
        }, function(data) {
            $('#agenda-container').removeClass('loading');
        }).fail(function() {
            alert('Server Error. Please refresh your browser and try again');
        });
    }

    function toggleIssue(li, val, callback) {
        $.post('', {
            issue : li.data('issue'),
            set : val
        }, function(data) {
            li.removeClass('loading');
        }).fail(function() {
            alert('Server Error. Please refresh your browser and try again');
        });
    }

    $('#agenda').on('click', '.addremove', function() {
        $(this).find('.ui-icon-minus').removeClass('ui-icon-minus').addClass('ui-icon-plus');
        var el = $(this).parent();
        el.addClass('loading');
        $("#available").append(el);
        toggleIssue(el, 1);
    }).sortable({
        'containment': $('#agenda').parent().parent(),
        'opacity': 0.6,
        cursorAt: { top: 25 },
        update: function(event, ui) {
            reorderIssues();
        }
    }).removeClass('ui-corner-all').filter('li').removeClass('ui-corner-bottom');

    $('#available').on('click', '.addremove', function() {
        $(this).find('.ui-icon-plus').removeClass('ui-icon-plus').addClass('ui-icon-minus');
        var el = $(this).parent();
        el.addClass('loading');
        $("#agenda").append(el);
        toggleIssue(el, 0);
    });

});
<|endoftext|>


<commit_before>goog.provide('ngeo.importOnlineDirective');

goog.require('ngeo.fileService');

(function() {

  var module = angular.module('ngeo.importOnlineDirective', [
    ngeo.fileService.module.name,
    'gettext'
  ]);
  ngeo.importOnlineDirective.module = module;

  /**
   * @constructor
   * @param {angular.$q} $q .
   * @param {angular.$timeout} $timeout .
   * @param {ngeo.File} ngeoFile .
   * @param {angularGettext.Catalog} gettextCatalog Gettext catalog.
   * @ngInject
   * @struct
   */
  var Directive = function($q, $timeout, ngeoFile, gettextCatalog) {

    var timeoutP;

    return {
      restrict: 'A',
      templateUrl: 'modules/import/partials/import-online.html',
      scope: {
        options: '=ngeoImportOnlineOptions'
      },
      link: function(scope, elt) {
        /**
         * @type {ngeox.ImportOnlineOptions}
         */
        var options = scope.options;
        if (!options || (typeof options.handleFileContent !== 'function')) {
          elt.remove();
          return;
        }

        scope.handleFileContent = options.handleFileContent;

        var initUserMsg = function() {
          scope.userMessage = 'connect';
          scope.progress = 0;
          scope.loading = false;
        };
        initUserMsg();

        // Create the typeAhead input for the list of urls available
        var taElt = elt.find('input[name=url]').typeahead({
          local: options.urls,
          limit: 500
        });

        // Fill the list of suggestions with all the data
        var initSuggestions = function() {
          var taView = $(taElt).data('ttView');
          var dataset = taView.datasets[0];
          dataset.getSuggestions('http', function(suggestions) {
            taView.dropdownView.renderSuggestions(dataset, suggestions);
          });
        };

        taElt.on('typeahead:initialized', function(evt) {
          // Re-initialize the list of suggestions
          initSuggestions();
        }).on('typeahead:selected', function(evt, datum) {
          // When a WMS is selected in the list, start downloading the
          // GetCapabilities
          scope.fileUrl = datum.value;
          scope.handleFileUrl();
          scope.$digest();
          // Re-initialize the list of suggestions
          initSuggestions();
        });

        // Toggle list of suggestions
        var taMenu = elt.find('.tt-dropdown-menu');
        elt.find('.ngeo-import-open').on('mousedown', function(evt) {
          if (taMenu.css('display') == 'none') {
            taElt.focus();
          } else {
            taElt.blur();
          }
          // Re-initialize the list of suggestions
          initSuggestions();
          evt.preventDefault();
        });

        scope.$on('gettextLanguageChanged', function() {
          if (scope.fileUrl && /lang=/.test(scope.fileUrl)) {
            scope.handleFileUrl();
          }
        });

        scope.cancel = function() {
          scope.progress = 0;
          if (scope.canceler) {
            scope.canceler.resolve();
            scope.canceler = null;
          }
        };

        scope.isValid = function(url) {
          if (options.isValidUrl) {
            return options.isValidUrl(url);
          }
          return true;
        };

        // Handle URL of WMS
        scope.handleFileUrl = function() {
          var url = scope.fileUrl;

          if (options.transformUrl) {
            url = options.transformUrl(url);
          }

          scope.canceler = $q.defer();
          scope.loading = true;
          scope.userMessage = 'uploading_file';
          $timeout.cancel(timeoutP);

          // Angularjs doesn't handle onprogress event
          ngeoFile.load(url, scope.canceler).then(function(fileContent) {
            scope.canceler = null;

            return scope.handleFileContent(fileContent, {
              url: scope.fileUrl
            });

          }).then(function(result) {
            scope.userMessage = result.message;

          }, function(err) {
            scope.userMessage = err.message;

          })['finally'](function() {
            scope.canceler = null;
            scope.loading = false;
            timeoutP = $timeout(initUserMsg, 10000);
          });
        };
      }
    };
  };

  module.directive('ngeoImportOnline', Directive);
})();
<commit_msg>Update typeahead code<commit_after>goog.provide('ngeo.importOnlineDirective');

goog.require('ngeo.fileService');

(function() {

  var module = angular.module('ngeo.importOnlineDirective', [
    ngeo.fileService.module.name,
    'gettext'
  ]);
  ngeo.importOnlineDirective.module = module;

  /**
   * @constructor
   * @param {angular.$q} $q .
   * @param {angular.$timeout} $timeout .
   * @param {ngeo.File} ngeoFile .
   * @param {angularGettext.Catalog} gettextCatalog Gettext catalog.
   * @ngInject
   * @struct
   */
  var Directive = function($q, $timeout, ngeoFile, gettextCatalog) {

    var timeoutP;

    return {
      restrict: 'A',
      templateUrl: 'modules/import/partials/import-online.html',
      scope: {
        options: '=ngeoImportOnlineOptions'
      },
      link: function(scope, elt) {
        /**
         * @type {ngeox.ImportOnlineOptions}
         */
        var options = scope.options;
        if (!options || (typeof options.handleFileContent !== 'function')) {
          elt.remove();
          return;
        }

        scope.handleFileContent = options.handleFileContent;

        var initUserMsg = function() {
          scope.userMessage = 'connect';
          scope.progress = 0;
          scope.loading = false;
        };
        initUserMsg();

        var substringMatcher = function(urls) {
          return function(q, cb) {
            var matches = [];
            if (!q) {
              matches = urls;
            } else {
              var regex = new RegExp(q, 'i');
              urls.forEach(function(url) {
                if (regex.test(url)) {
                  matches.push(url);
                }
              });
            }
            cb(matches);
          };
        };

        // Create the typeAhead input for the list of urls available
        var taElt = elt.find('input[name=url]').typeahead({
          hint: true,
          highlight: true,
          minLength: 0
        }, {
          name: 'wms',
          limit: 500,
          source: substringMatcher(scope.options.urls)
        }).on('typeahead:selected', function(evt, url) {
          taElt.typeahead('close');
          // When a WMS is selected in the list, start downloading the
          // GetCapabilities
          scope.fileUrl = url;
          scope.handleFileUrl();
          scope.$digest();
        }).on('focus', function() {
        });

        scope.$on('gettextLanguageChanged', function() {
          if (scope.fileUrl && /lang=/.test(scope.fileUrl)) {
            scope.handleFileUrl();
          }
        });

        scope.cancel = function() {
          scope.progress = 0;
          if (scope.canceler) {
            scope.canceler.resolve();
            scope.canceler = null;
          }
        };

        scope.isValid = function(url) {
          if (options.isValidUrl) {
            return options.isValidUrl(url);
          }
          return true;
        };

        // Handle URL of WMS
        scope.handleFileUrl = function() {
          var url = scope.fileUrl;

          if (options.transformUrl) {
            url = options.transformUrl(url);
          }

          scope.canceler = $q.defer();
          scope.loading = true;
          scope.userMessage = 'uploading_file';
          $timeout.cancel(timeoutP);

          // Angularjs doesn't handle onprogress event
          ngeoFile.load(url, scope.canceler).then(function(fileContent) {
            scope.canceler = null;

            return scope.handleFileContent(fileContent, {
              url: scope.fileUrl
            });

          }).then(function(result) {
            scope.userMessage = result.message;

          }, function(err) {
            scope.userMessage = err.message;

          })['finally'](function() {
            scope.canceler = null;
            scope.loading = false;
            timeoutP = $timeout(initUserMsg, 10000);
          });
        };
      }
    };
  };

  module.directive('ngeoImportOnline', Directive);
})();
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
  View,
  Text,
  ScrollView,
  Dimensions,
  StyleSheet
} from 'react-native';
import FastImage from 'react-native-fast-image';
import axios from 'axios';

import {URL} from '../../constants';
import MarkdownHelper from '../../utils/MarkdownHelper';
import NativeHtmlViewRender from '../../wdui/NativeHtmlViewRender';
import Divider from '../../wdui/Divider';
import Loading from '../../wdui/loading/Loading';
import normalize from '../../wdui/helpers/normalizeText';

const deviceWidth = Dimensions.get('window').width;

class PlayDetailView extends Component {
  static displayName = 'PlayDetailView';

  static navigationOptions = ({navigation}) => ({
    title: `玩法: ${navigation.state.params.title}`
  });

  static propTypes = {
    navigate: PropTypes.func.isRequired
  };

  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      data: props.navigation.state && props.navigation.state.params ? props.navigation.state.params : null
    };
  }

  componentWillMount() {
    if (this.props.navigation.state.params && this.props.navigation.state.params.slug) {
      this.setState({
        loading: true
      })
      let slug = this.props.navigation.state.params.slug;
      axios.get(URL.PLAY + '?slug=' + slug)
        .then(response => {
          this.props.navigation.setParams({title: response.data.results[0].title});
          this.setState({
            data: response.data.results[0],
            loading: false
          });
        });
    }
  }

  render() {
    let data = this.state.data;
    if (!data.content || this.state.loading) {
      return <Loading text={'数据加载中'} />;
    }
    const htmlContent = MarkdownHelper.convert(data.content, {width: deviceWidth});

    return (
      <View style={styles.container}>
        <ScrollView>
          <View style={{paddingBottom: 15}}>
            { data.featured_image
              ? <FastImage
                style={{width: deviceWidth, height: (deviceWidth) * 0.4}}
                resizeMode={FastImage.resizeMode.cover}
                source={{
                  uri: URL.IMAGE_BASE + data.featured_image
                }}
              />
              : <View />
            }
          </View>
          <Text style={styles.title}>{ data.title }</Text>
          <View style={styles.authorInfo}>
            <Text style={styles.author}>{ data.user }</Text>
          </View>
          <Divider />
          <NativeHtmlViewRender
            html={htmlContent}
          />
          <Divider />
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  title: {
    color: '#384452',
    alignItems: 'center',
    fontSize: normalize(18),
    padding: 10,
    backgroundColor: '#fff'
  },
  authorInfo: {
    alignItems: 'center',
    backgroundColor: '#fff'
  },
  author: {
    color: '#384452',
    fontSize: normalize(12),
    padding: 5,
    backgroundColor: '#fff'
  }
});

export default PlayDetailView;
<commit_msg>[APP INDEXING] fix condition issue<commit_after>import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
  View,
  Text,
  ScrollView,
  Dimensions,
  StyleSheet
} from 'react-native';
import FastImage from 'react-native-fast-image';
import axios from 'axios';

import {URL} from '../../constants';
import MarkdownHelper from '../../utils/MarkdownHelper';
import NativeHtmlViewRender from '../../wdui/NativeHtmlViewRender';
import Divider from '../../wdui/Divider';
import Loading from '../../wdui/loading/Loading';
import normalize from '../../wdui/helpers/normalizeText';

const deviceWidth = Dimensions.get('window').width;

class PlayDetailView extends Component {
  static displayName = 'PlayDetailView';

  static navigationOptions = ({navigation}) => ({
    title: `玩法: ${navigation.state.params.title}`
  });

  static propTypes = {
    navigate: PropTypes.func.isRequired
  };

  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      data: props.navigation.state && props.navigation.state.params ? props.navigation.state.params : null
    };
  }

  componentWillMount() {
    let params = this.props.navigation.state.params;
    if (params && !params.content && params.slug) {
      this.setState({
        loading: true
      })
      let slug = params.slug;
      axios.get(URL.PLAY + '?slug=' + slug)
        .then(response => {
          this.props.navigation.setParams({title: response.data.results[0].title});
          this.setState({
            data: response.data.results[0],
            loading: false
          });
        });
    }
  }

  render() {
    let data = this.state.data;
    if (!data.content || this.state.loading) {
      return <Loading text={'数据加载中'} />;
    }
    const htmlContent = MarkdownHelper.convert(data.content, {width: deviceWidth});

    return (
      <View style={styles.container}>
        <ScrollView>
          <View style={{paddingBottom: 15}}>
            { data.featured_image
              ? <FastImage
                style={{width: deviceWidth, height: (deviceWidth) * 0.4}}
                resizeMode={FastImage.resizeMode.cover}
                source={{
                  uri: URL.IMAGE_BASE + data.featured_image
                }}
              />
              : <View />
            }
          </View>
          <Text style={styles.title}>{ data.title }</Text>
          <View style={styles.authorInfo}>
            <Text style={styles.author}>{ data.user }</Text>
          </View>
          <Divider />
          <NativeHtmlViewRender
            html={htmlContent}
          />
          <Divider />
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  title: {
    color: '#384452',
    alignItems: 'center',
    fontSize: normalize(18),
    padding: 10,
    backgroundColor: '#fff'
  },
  authorInfo: {
    alignItems: 'center',
    backgroundColor: '#fff'
  },
  author: {
    color: '#384452',
    fontSize: normalize(12),
    padding: 5,
    backgroundColor: '#fff'
  }
});

export default PlayDetailView;
<|endoftext|>


<commit_before>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

(function()
{
  var globalId = 0;

  /**
   * Models are the heart of any JavaScript application,
   * containing the interactive data as well as a large
   * part of the logic surrounding it: conversions, validations,
   * computed properties, and access control. You extend `core.mvc.model.Model`
   * with your domain-specific methods, and `Model` provides a basic
   * set of functionality for managing changes.
   */
  core.Class("core.mvc.model.Model",
  {
    include: [core.property.MGeneric, core.event.MEventTarget],
    implement : [core.mvc.model.IModel],

    /**
     * Initial data structure is imported from @values {Map}.
     */
    construct: function(values)
    {
      if (jasy.Env.isSet("debug"))
      {
        if (values != null) {
          core.Assert.isType(values, "Map", "Invalid values to import!");
        }
      }

      // Automatically created client-side ID
      this.__clientId = "model:" + (globalId++);

      // Import given values
      if (values != null) {
        this.set(values);
      }
    },

    events :
    {
      /** Fired whenever the model is changed in a way that is interesting for listeners */
      "change" : core.event.Simple
    },

    members:
    {
      error : function(message) {
        console.error("Model Error: " + message);
      },

      __id : null,

      // Interface implementation
      getId : function() {
        return this.__id;
      },

      // Interface implementation
      setId : function(id) {
        return this.__id = id;
      },

      __clientId : null,

      // Interface implementation
      getClientId : function() {
        return this.__clientId;
      },

      // Interface implementation
      toJSON : function() {
        return this.get(Object.keys(core.Class.getProperties(this.constructor)));
      },

      // Interface implementation
      sync : function() {
        return core.mvc.Sync.sync(this);
      }
    }
  });
})();
<commit_msg>Improved toJSON to call toJSON on property values<commit_after>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

(function()
{
  var globalId = 0;

  /**
   * Models are the heart of any JavaScript application,
   * containing the interactive data as well as a large
   * part of the logic surrounding it: conversions, validations,
   * computed properties, and access control. You extend `core.mvc.model.Model`
   * with your domain-specific methods, and `Model` provides a basic
   * set of functionality for managing changes.
   */
  core.Class("core.mvc.model.Model",
  {
    include: [core.property.MGeneric, core.event.MEventTarget],
    implement : [core.mvc.model.IModel],

    /**
     * Initial data structure is imported from @values {Map}.
     */
    construct: function(values)
    {
      if (jasy.Env.isSet("debug"))
      {
        if (values != null) {
          core.Assert.isType(values, "Map", "Invalid values to import!");
        }
      }

      // Automatically created client-side ID
      this.__clientId = "model:" + (globalId++);

      // Import given values
      if (values != null) {
        this.set(values);
      }
    },

    events :
    {
      /** Fired whenever the model is changed in a way that is interesting for listeners */
      "change" : core.event.Simple
    },

    members:
    {
      error : function(message) {
        console.error("Model Error: " + message);
      },

      __id : null,

      // Interface implementation
      getId : function() {
        return this.__id;
      },

      // Interface implementation
      setId : function(id) {
        return this.__id = id;
      },

      __clientId : null,

      // Interface implementation
      getClientId : function() {
        return this.__clientId;
      },

      // Interface implementation
      toJSON : function()
      {
        return this.get(Object.keys(core.Class.getProperties(this.constructor))).map(function(value) {
          value.toJSON ? value.toJSON() : value
        });
      },

      // Interface implementation
      sync : function() {
        return core.mvc.Sync.sync(this);
      }
    }
  });
})();
<|endoftext|>


<commit_before>var oldVal = "";
var newVal = "";
var thisObj = null;
var timeout;
var l;
var working = false;

function btnConfirm(btnThis){
    if(!working){
        l = Ladda.create(btnThis);
        l.start();
        working = true;
        clearTimeout(timeout);
        $('#alertbox').fadeOut(100);

        $.ajax({
            type: "GET",
            url: '?p=json&r=edit&d='+(thisObj.parent().parent().attr('id'))+'&f='+(thisObj.parent().index())+'&n='+newVal
        }).done(handleresponse).fail(function(){console.log('Something has gone very wrong');btnDeny();});
    }
}

function btnDeny(){
    if(thisObj != null){
        thisObj.popover('destroy');
        thisObj.html(oldVal);
        thisObj = null;
    }
}

$(".editable").click( function(){
    if( $(this).children().length == 0 && thisObj == null ){
        oldVal = $(this).text();
        $(this).html('<input type="text" class="form-control edit input-sm" value="'+ $(this).text() +'" autocomplete="off">');
        $("input.form-control.edit").focus();
        $("input.edit").focusout(
            function(){
                thisObj = $(this).parent();
                thisObj.popover({
                    placement: 'bottom',
                    html: 'true',
                    trigger: 'manual',
                    title: 'Confirm edit',
                    content: '
<button type="button" class="btn btn-default ladda-button" data-style="slide-up" onclick="btnConfirm(this)">Yes</button><button type="button" class="btn btn-default ladda-button" data-style="slide-up" onclick="btnDeny()">No</button>
'
                }).on('hide', function(){
                    btnDeny();
                });
                thisObj.popover('show');
                newVal = $(this).val();
                $(this).replaceWith( $(this).val() );
            }
        )
    }
});

handleresponse = function (msg) {
    l.stop();

    working = false;
    var level='danger';
    var title='';
    if(msg.code=="success"){
        thisObj.popover('destroy');
        thisObj = null;
        level='success';
        title='Edit saved';
    } else if(msg.code=="failure"){
        btnDeny();
        level='warning';
        title='Edit failed';
    } else if(msg.code=="nothing"){
        btnDeny();
        level='info';
        title='Nothing to update';
    } else {
        btnDeny();
        level='danger';
        title='Something broke...';
    }
    $('#alertbox').html('
'+title+'
');
    $('#alertbox').fadeIn(200);
    timeout=setTimeout(function(){$('#alertbox').fadeOut(100);},3000);
}<commit_msg>remove verification when input doesn't change<commit_after>var oldVal = "";
var newVal = "";
var thisObj = null;
var timeout;
var l;
var working = false;

function btnConfirm(btnThis){
    if(!working){
        l = Ladda.create(btnThis);
        l.start();
        working = true;
        clearTimeout(timeout);
        $('#alertbox').fadeOut(100);

        $.ajax({
            type: "GET",
            url: '?p=json&r=edit&d='+(thisObj.parent().parent().attr('id'))+'&f='+(thisObj.parent().index())+'&n='+newVal
        }).done(handleresponse).fail(function(){console.log('Something has gone very wrong');btnDeny();});
    }
}

function btnDeny(){
    if(thisObj != null){
        thisObj.popover('destroy');
        thisObj.html(oldVal);
        thisObj = null;
    }
}

$(".editable").click( function(){
    if( $(this).children().length == 0 && thisObj == null ){
        oldVal = $(this).text();
        $(this).html('<input type="text" class="form-control edit input-sm" value="'+ $(this).text() +'" autocomplete="off">');
        $("input.form-control.edit").focus();
        $("input.edit").focusout(
            if ($(this).val() == $(this).attr('value')) {
                function(){
                    thisObj = $(this).parent();
                    thisObj.popover({
                        placement: 'bottom',
                        html: 'true',
                        trigger: 'manual',
                        title: 'Confirm edit',
                        content: '
<button type="button" class="btn btn-default ladda-button" data-style="slide-up" onclick="btnConfirm(this)">Yes</button><button type="button" class="btn btn-default ladda-button" data-style="slide-up" onclick="btnDeny()">No</button>
'
                    }).on('hide', function(){
                        btnDeny();
                    });
                    thisObj.popover('show');
                    newVal = $(this).val();
                    $(this).replaceWith( $(this).val() );
                }
            }
        )
    }
});

handleresponse = function (msg) {
    l.stop();

    working = false;
    var level='danger';
    var title='';
    if(msg.code=="success"){
        thisObj.popover('destroy');
        thisObj = null;
        level='success';
        title='Edit saved';
    } else if(msg.code=="failure"){
        btnDeny();
        level='warning';
        title='Edit failed';
    } else if(msg.code=="nothing"){
        btnDeny();
        level='info';
        title='Nothing to update';
    } else {
        btnDeny();
        level='danger';
        title='Something broke...';
    }
    $('#alertbox').html('
'+title+'
');
    $('#alertbox').fadeIn(200);
    timeout=setTimeout(function(){$('#alertbox').fadeOut(100);},3000);
}<|endoftext|>


<commit_before>$(function() {
	smoothScrool(300);
	workBelt();
	workLoad();
});

function smoothScrool (duration) {
	$('a[href^="#"]').on('click', function(event) {

	    var target = $( $(this).attr('href') );

	    if( target.length ) {
	        event.preventDefault();
	        $('html, body').animate({
	            scrollTop: target.offset().top
	        }, duration);
	    }
	});
}

function workBelt() {

  $('.thumb-unit').click(function() {
    $('.work-belt').css('left','-100%');
    $('.work-container').show();
  });

  $('.work-return').click(function() {
    $('.work-belt').css('left','0%');
    $('.work-container').hide(800);
  });

}

function  workLoad() {

  $.ajaxSetup({ cache: true });

  $('.thumb-unit').click(function() {
    var $this = $(this),
        newTitle = $this.find('strong').text(),
        newfolder = $this.data('folder'),
        spinner = '
Loading...
',
        newHTML = '/work/'+ newfolder +'.html';
    $('.project-load').html(spinner).load(newHTML);
    $('.project-title').text(newTitle);
  });

}

<commit_msg>Fixed project loading url<commit_after>$(function() {
	smoothScrool(300);
	workBelt();
	workLoad();
});

function smoothScrool (duration) {
	$('a[href^="#"]').on('click', function(event) {

	    var target = $( $(this).attr('href') );

	    if( target.length ) {
	        event.preventDefault();
	        $('html, body').animate({
	            scrollTop: target.offset().top
	        }, duration);
	    }
	});
}

function workBelt() {

  $('.thumb-unit').click(function() {
    $('.work-belt').css('left','-100%');
    $('.work-container').show();
  });

  $('.work-return').click(function() {
    $('.work-belt').css('left','0%');
    $('.work-container').hide(800);
  });

}

function  workLoad() {

  $.ajaxSetup({ cache: true });

  $('.thumb-unit').click(function() {
    var $this = $(this),
        newTitle = $this.find('strong').text(),
        newfolder = $this.data('folder'),
        spinner = '
Loading...
',
        newHTML = newfolder + '/work/' +'.html';
    $('.project-load').html(spinner).load(newHTML);
    $('.project-title').text(newTitle);
  });

}

<|endoftext|>


<commit_before>/*
* @Author: Town
* @Date:   2017-12-05 01:29:40
* @Last Modified by:   Town
* @Last Modified time: 2017-12-05 11:55:51
*/
$(document).ready(function(){

    /**
     * 响应式导航
     */
    $('#menu-toggle').on('click', function(e){

        $('.g-nav').slideToggle(200);

        $(document).one('click', function(){
            $('.g-nav').slideUp(200);
        });

        e.stopPropagation();
    });

    $('.g-nav').on('click', function(e){
        e.stopPropagation();
    });

   /**
    * 标题栏
    */
    if($(window).width() > 695) {

        var header = $('.g-header');
        var header_h = header.outerHeight();
        var appLogo = $('.g-logo');
        var navText = $('.g-nav a');

        var themeColorFlag = $('.g-banner').attr('data-theme');

        var scFlag = $(document).scrollTop();

        $(document).scroll(function(){

            var scrollTop = $(this).scrollTop();

            if(scrollTop > header_h) {

                if(scrollTop > 3*header_h) {
                    header.addClass('headerUp');
                }
                header.css({
                    'background-color': 'rgba(255, 255, 255, .98)',
                    'box-shadow': '0 1px 12px rgba(0, 0, 0, .08)'
                });
                appLogo.css({
                    'background': 'url(/assets/icons/logo_' + themeColorFlag + '.svg) no-repeat center',
                    'background-size': '100% 100%'
                });
                navText.css('color', '#666');
                $('.g-nav').addClass('nav-' + themeColorFlag);

            }else{

                header.removeClass('headerUp');
                header.css({
                    'background-color': 'transparent',
                    'box-shadow': 'none'
                });
                appLogo.css({
                    'background': 'url(/assets/icons/logo.svg) no-repeat center',
                    'background-size': '100% 100%'
                });
                navText.css('color', '#fff');
                $('.g-nav').removeClass('nav-' + themeColorFlag);

            }
            // 滚动动作
            if(scFlag > scrollTop) {
                header.addClass('headerDown');
            }else{
                header.removeClass('headerDown');
            }
            scFlag = scrollTop;
        });
    }

    /*
    *后套的调整
    */
    function postCover(img, container) {
        var imgWidth = img.width(),
            containerWidth = container.width(),
            imgHeight = img.height(),
            containerHeight = container.height();
        var isOk = false;
        if(imgHeight < containerHeight) {
            img.css({
                'width': 'auto',
                'height': '100%'
            });
            imgWidth = img.width(),
            containerWidth = container.width();
            var marginLeft = (imgWidth - containerWidth) / 2;
            img.css('margin-left', '-' + marginLeft + 'px');
            isOk = true;
        } else {
            var marginTop = (containerHeight - imgHeight) / 2;
            img.css('margin-top', marginTop + 'px');
            isOk = true;
        }

        if(isOk) {
            img.fadeIn();
            isOk = false;
        }
    }

    /**
     * 后导航仪
     */
    $('.read-next-item section').each(function(){
        var _this = $(this),
            n = _this.height(),
            rn = $('.read-next-item').height();
        _this.css('margin-top', (rn-n)/2 + 'px');
        _this.fadeIn();
    });

    $('.read-next-item img').each(function(){
        var _this = $(this);
        postCover(_this, $('.read-next-item'));
    });

    /**
     * 分页
     */
    function pagination() {
        var total = parseInt($('#total_pages').val()),
            current = parseInt($('#current_pages').val()),
            baseUrl = $('#base_url').val(),
            limit = 3;

        var link_html = '';

        for(var i = current - limit; i<current; i++) {
            if(i>0 && i!==1) {
                link_html += '' + i + '';
            }else if(i===1) {
                link_html += '' + i + '';
            }
        }

        link_html += '' + current + '';

        for(var j = current + 1; j<=current + limit; j++) {
            if(j<=total) {
                link_html += '' + j + '';
            }
        }

        $('#page-link-container').html(link_html);
    }
    pagination();

    /**
     * 搜索
     */
    function Search() {
        var self = this,
            input = $('#search_input'),
            result = $('.search_result');

        input.focus(function() {
            $('.icon-search').css('color', '#3199DB');
            result.show();
        });

        input.keyup(debounce(this.autoComplete));

        $(document).click(function(e) {
            if(e.target.id === 'search_input' || e.target.className === 'search_result' || e.target.className === 'search_item') {
                return;
            }
            $('.icon-search').css('color', '#CAD3DC');
            result.hide();
        });
    }

    Search.prototype.autoComplete = function() {
        var keywords = this.value.toLowerCase();

        if(keywords.length) {
            $('.icon-search').css('color', '#3199DB');
        }else{
            $('.icon-search').css('color', '#CAD3DC');
        }

        $.getJSON('../../search.json').done(function(data) {
            var html = '';
            for (var i in data) {
                var item = data[i],
                    title = item.title,
                    tags = item.tags,
                    url = item.url;

                var k = title + tags;
                if(keywords !== '' && k.toLowerCase().indexOf(keywords) >= 0) {
                    html += '' + item.title + '';
                }
            }
            $('.search_result').html(html);
        });
    };

    function debounce(fn, delay) {
        var timer;
        delay = delay || 120;

        return function() {
            var ctx = this,
                args = arguments,
                later = function() {
                    fn.apply(ctx, args);
                };
            clearTimeout(timer);
            timer = setTimeout(later, delay);
        };
    }

    new Search();

    /**
     * 夜间模式
     */
    function nightMode() {
        var el = $('body'),
            className = 'night-mode';

        var date = new Date(),
            hour = date.getHours();

        if((hour >= 0 && hour <= 6) || hour === 23) {
            el.addClass(className);
        }
    }

    if($('#nm-switch').val() === 'true') {
        nightMode();
    }

    /**
     * 复制版权
     */
    function setClipboardData(str) {
        str += '\n\n著作权归作者所有。\n商业转载请联系作者获得授权,非商业转载请注明出处。\n原文: ' + location.href;
        $('.post-content').on('copy', function(e) {
            var data = window.clipboardData || e.originalEvent.clipboardData;
            data.setData('text/plain', str);
            e.preventDefault();
        });
    }
    $('.post-content').on('mouseup', function(e) {
        var txt = window.getSelection();
        if(txt.toString().length >= 30) {
            setClipboardData(txt);
        }
    });

});

<commit_msg>Signed-off-by: Twon <android@twonwang.com><commit_after>/*
* @Author: Town
* @Date:   2017-12-05 01:29:40
* @Last Modified by:   Town
* @Last Modified time: 2017-12-06 09:21:21
*/
$(document).ready(function(){

    /**
     * 响应式导航
     */
    $('#menu-toggle').on('click', function(e){

        $('.g-nav').slideToggle(200);

        $(document).one('click', function(){
            $('.g-nav').slideUp(200);
        });

        e.stopPropagation();
    });

    $('.g-nav').on('click', function(e){
        e.stopPropagation();
    });

   /**
    * 标题栏
    */
    if($(window).width() > 695) {

        var header = $('.g-header');
        var header_h = header.outerHeight();
        var appLogo = $('.g-logo');
        var navText = $('.g-nav a');

        var themeColorFlag = $('.g-banner').attr('data-theme');

        var scFlag = $(document).scrollTop();

        $(document).scroll(function(){

            var scrollTop = $(this).scrollTop();

            if(scrollTop > header_h) {

                if(scrollTop > 3*header_h) {
                    header.addClass('headerUp');
                }
                header.css({
                    'background-color': 'rgba(255, 255, 255, .98)',
                    'box-shadow': '0 1px 12px rgba(0, 0, 0, .08)'
                });
                appLogo.css({
                    'background': 'url(/assets/icons/logo_' + themeColorFlag + '.svg) no-repeat center',
                    'background-size': '100% 100%'
                });
                navText.css('color', '#666');
                $('.g-nav').addClass('nav-' + themeColorFlag);

            }else{

                header.removeClass('headerUp');
                header.css({
                    'background-color': 'transparent',
                    'box-shadow': 'none'
                });
                appLogo.css({
                    'background': 'url(/assets/icons/logo.svg) no-repeat center',
                    'background-size': '100% 100%'
                });
                navText.css('color', '#fff');
                $('.g-nav').removeClass('nav-' + themeColorFlag);

            }
            // 滚动动作
            if(scFlag > scrollTop) {
                header.addClass('headerDown');
            }else{
                header.removeClass('headerDown');
            }
            scFlag = scrollTop;
        });
    }

    /*
    *后套的调整
    */
    function postCover(img, container) {
        var imgWidth = img.width(),
            containerWidth = container.width(),
            imgHeight = img.height(),
            containerHeight = container.height();
        var isOk = false;
        if(imgHeight < containerHeight) {
            img.css({
                'width': 'auto',
                'height': '100%'
            });
            imgWidth = img.width(),
            containerWidth = container.width();
            var marginLeft = (imgWidth - containerWidth) / 2;
            img.css('margin-left', '-' + marginLeft + 'px');
            isOk = true;
        } else {
            var marginTop = (containerHeight - imgHeight) / 2;
            img.css('margin-top', marginTop + 'px');
            isOk = true;
        }

        if(isOk) {
            img.fadeIn();
            isOk = false;
        }
    }

    /**
     * 后导航仪
     */
    $('.read-next-item section').each(function(){
        var _this = $(this),
            n = _this.height(),
            rn = $('.read-next-item').height();
        _this.css('margin-top', (rn-n)/2 + 'px');
        _this.fadeIn();
    });

    $('.read-next-item img').each(function(){
        var _this = $(this);
        postCover(_this, $('.read-next-item'));
    });

    /**
     * 分页
     */
    function pagination() {
        var total = parseInt($('#total_pages').val()),
            current = parseInt($('#current_pages').val()),
            baseUrl = $('#base_url').val(),
            limit = 3;

        var link_html = '';

        for(var i = current - limit; i<current; i++) {
            if(i>0 && i!==1) {
                link_html += '' + i + '';
            }else if(i===1) {
                link_html += '' + i + '';
            }
        }

        link_html += '' + current + '';

        for(var j = current + 1; j<=current + limit; j++) {
            if(j<=total) {
                link_html += '' + j + '';
            }
        }

        $('#page-link-container').html(link_html);
    }
    pagination();

    /**
     * 搜索
     */
    function Search() {
        var self = this,
            input = $('#search_input'),
            result = $('.search_result');

        input.focus(function() {
            $('.icon-search').css('color', '#3199DB');
            result.show();
        });

        input.keyup(debounce(this.autoComplete));

        $(document).click(function(e) {
            if(e.target.id === 'search_input' || e.target.className === 'search_result' || e.target.className === 'search_item') {
                return;
            }
            $('.icon-search').css('color', '#CAD3DC');
            result.hide();
        });
    }

    Search.prototype.autoComplete = function() {
        var keywords = this.value.toLowerCase();

        if(keywords.length) {
            $('.icon-search').css('color', '#3199DB');
        }else{
            $('.icon-search').css('color', '#CAD3DC');
        }

        $.getJSON('../../search.json').done(function(data) {
            var html = '';
            for (var i in data) {
                var item = data[i],
                    title = item.title,
                    tags = item.tags,
                    url = item.url;

                var k = title + tags;
                if(keywords !== '' && k.toLowerCase().indexOf(keywords) >= 0) {
                    html += '' + item.title + '';
                }
            }
            $('.search_result').html(html);
        });
    };

    function debounce(fn, delay) {
        var timer;
        delay = delay || 120;

        return function() {
            var ctx = this,
                args = arguments,
                later = function() {
                    fn.apply(ctx, args);
                };
            clearTimeout(timer);
            timer = setTimeout(later, delay);
        };
    }

    new Search();

    /**
     * 夜间模式
     */
    function nightMode() {
        var el = $('body'),
            className = 'night-mode';

        var date = new Date(),
            hour = date.getHours();

        if((hour >= 0 && hour <= 22) || hour === 23) {
            el.addClass(className);
        }
    }

    if($('#nm-switch').val() === 'true') {
        nightMode();
    }

    /**
     * 复制版权
     */
    function setClipboardData(str) {
        str += '\n\n著作权归作者所有。\n商业转载请联系作者获得授权,非商业转载请注明出处。\n原文: ' + location.href;
        $('.post-content').on('copy', function(e) {
            var data = window.clipboardData || e.originalEvent.clipboardData;
            data.setData('text/plain', str);
            e.preventDefault();
        });
    }
    $('.post-content').on('mouseup', function(e) {
        var txt = window.getSelection();
        if(txt.toString().length >= 30) {
            setClipboardData(txt);
        }
    });

});

<|endoftext|>


<commit_before>var teammoldeApp = angular.module(
	"teammoldeApp",
	[
		'ngAnimate', 'ui.router'
	]
);

teammoldeApp
.config(
[
'$stateProvider', '$urlRouterProvider', '$sceProvider',
function ($stateProvider, $urlRouterProvider, $sceProvider)
{
	$sceProvider.enabled(false);

	$urlRouterProvider
		.otherwise('/');

	$stateProvider
		.state('home', {
			url: '/',
			views: {
				"main": {
					templateUrl: '/partials/home.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('priser', {
			url: '/priser',
			views: {
				"main": {
					templateUrl: '/partials/priser.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('larere', {
			url: '/larere',
			views: {
				"main": {
					templateUrl: '/partials/laerere.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('bestill', {
			url: '/bestill',
			views: {
				"main": {
					templateUrl: '/partials/bestill.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('elevside', {
			url: '/elevside',
			views: {
				"main": {
					templateUrl: '/partials/elevside.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('manedensbestatt', {
			url: '/manedensbestatt',
			views: {
				"main": {
					templateUrl: '/partials/manedensbestatt.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('kontakt', {
			abstract: true,
			url: '/kontakt',
			views: {
				"main": {
					templateUrl: '/partials/kontakt.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})
	;

}
]
);

teammoldeApp
.filter('bstableizer',
function () {
	return function ( markup ) {
		return markup.replace('
', '
');
	};
}
);

teammoldeApp
.controller('homeCtrl',
[
'$scope', 'bgSVG',
function($scope, bgSVG) {
	bgSVG.init().then(function(){
		bgSVG.go();
	});
}
]
);

teammoldeApp
.controller('PriserCtrl',
[
'$scope', 'wpData', 'bgSVG',
function($scope, wpData, bgSVG) {
	$scope.pricelist = '';

	wpData.getPage('priser')
		.then(function(html) {
			$scope.pricelist = html;
		});

	//bgSVG.blur(true);
}
]
);

teammoldeApp
.service('wpData',
[
'$q', '$http',
function ( $q, $http )
{
	this.getPage = function( url ) {
		var deferred = $q.defer();

		$http.get('wordpress/' + url + '/?json=1', {cache: true})
			.success(function(result) {
				deferred.resolve(result.page.content);
			})
			.error(function(){
				deferred.reject();
			});

		return deferred.promise;
	};
}
]
);

teammoldeApp
.service('bgSVG',
[
'$q', 'Tween',
function ( $q, Tween )
{
	var s,
		objects = {},
		self = this;

	this.init = function() {
		var deferred = $q.defer();

		s = Snap("#background");

		Snap.load("assets/svg/background.svg", function (f) {
			s.append(f);

			objects.cloud_left = Snap(s).select('#cloud-left');
			objects.cloud_right = Snap(s).select('#cloud-right');

			objects.cloud_left.attr({transform: 'translate(400,0)'});
			objects.cloud_right.attr({transform: 'translate(-400,0)'});

			objects.personbil = Snap(s).select('#personbil');

			objects.lett_lastebil = Snap(s).select('#lett-lastebil');

			objects.lastebil = Snap(s).select('#lastebil');

			objects.buss = Snap(s).select('#buss');

			deferred.resolve();
		});

		return deferred.promise;
	};

	this.go = function() {
		Tween.get(objects.cloud_left)
			.animate({transform: 'translate(600,0)'},10000, mina.easeinout)
			.animate({transform: 'translate(1000,0)'},7500, mina.easeinout)
			.animate({transform: 'translate(1800,0)'},7500, mina.easeinout)
			.animate({transform: 'translate(2200,0)'},7500, mina.easeinout)
			.animate({transform: 'translate(2600,0)'},7500, mina.easeinout)
			.action(function(){
				objects.cloud_left.attr({transform: 'translate(0,0)'});
			})
		;

		Tween.get(objects.cloud_right)
			.animate({transform: 'translate(-600,0)'},5000, mina.easeinout)
			.animate({transform: 'translate(-1000,0)'},10000, mina.easeinout)
			.animate({transform: 'translate(-1500,0)'},7500, mina.easeinout)
			.animate({transform: 'translate(-2200,0)'},10000, mina.easeinout)
			.animate({transform: 'translate(-2600,0)'},7500, mina.easeinout)
			.action(function(){
				objects.cloud_right.attr({transform: 'translate(0,0)'});
			})
		;

		Tween.get(objects.personbil)
			.animate({transform: 'translate(700,0)'}, 2000, mina.easeinout)
			.animate({transform: 'translate(700,0)'}, 500, mina.linear)
			.animate({transform: 'translate(900,0)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(900,0)'}, 500, mina.linear)
			.animate({transform: 'translate(1300,0)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(1300,0)'}, 500, mina.linear)
			.animate({transform: 'translate(1600,0)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(1850,0) scale(-1, 1)'}, 1000, mina.easeinout)
			.animate({transform: 'translate(1600,0) scale(-1, 1)'}, 2500, mina.linear)
			.animate({transform: 'translate(1300,0) scale(-1, 1)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(700,0) scale(-1, 1)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(250,0) scale(-1, 1)'}, 1000, mina.easeinout)
			.animate({transform: 'translate(0,0) scale(1, 1)'}, 1000, mina.easeinout)
		;

		Tween.get(objects.lett_lastebil)
			.animate({transform: 'translate(-200,0)'}, 3000, mina.easeinout)
			.animate({transform: 'translate(-200,0)'}, 500, mina.linear)
			.animate({transform: 'translate(-400,0)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(-400,0)'}, 500, mina.linear)
			.animate({transform: 'translate(-800,0)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(2000,0) scale(-1, 1)'}, 2000, mina.easeinout)
			.animate({transform: 'translate(2000,0) scale(-1, 1)'}, 2500, mina.linear)
			.animate({transform: 'translate(2400,0) scale(-1, 1)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(3000,0) scale(-1, 1)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(3200,0) scale(-1, 1)'}, 1000, mina.easeinout)
			.animate({transform: 'translate(800,0) scale(1, 1)'}, 1000, mina.easeinout)
		;

		Tween.get(objects.lastebil)
			.animate({transform: 'translate(-200,0)'}, 3000, mina.easeinout)
			.animate({transform: 'translate(-200,0)'}, 100, mina.linear)
			.animate({transform: 'translate(-800,0)'}, 9000, mina.easeinout)
			.animate({transform: 'translate(2000,0) scale(-1, 1)'}, 2000, mina.easeinout)
			.animate({transform: 'translate(2000,0) scale(-1, 1)'}, 2500, mina.linear)
			.animate({transform: 'translate(2400,0) scale(-1, 1)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(3000,0) scale(-1, 1)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(3200,0) scale(-1, 1)'}, 1000, mina.easeinout)
			.animate({transform: 'translate(800,0) scale(1, 1)'}, 1000, mina.easeinout)
		;

		Tween.get(objects.buss)
			.animate({transform: 'translate(0,0)'}, 2500, mina.linear)
			.animate({transform: 'translate(-200,0)'}, 3000, mina.easeinout)
			.animate({transform: 'translate(-200,0)'}, 500, mina.linear)
			.animate({transform: 'translate(-400,0)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(-400,0)'}, 500, mina.linear)
			.animate({transform: 'matrix(0.8660254,0.5,-0.5,0.8660254,-24.308937,-698.29248)'}, 5000, mina.easeinout)
			.animate({transform: 'matrix(0.94967542,0.31323569,-0.31323569,0.94967542,-374.13056,-520.01597)'}, 5000, mina.linear)
			.animate({transform: 'matrix(0.98814356,0.15353273,-0.15353273,0.98814356,-656.74677,-340.16701)'}, 2500, mina.linear)
			.animate({transform: 'translate(-897,-131)'}, 2500, mina.linear)
			.action(function(){
				objects.buss.attr({transform: 'translate(0,0)'});
			})
		;
	};

	this.blur = function( blur ) {
		s.attr({
			filter: blur ? f : null
		});
	};
}
]
);

teammoldeApp
.service('Tween',
[
'$q',
function ( $q )
{
	var tween = function( element ) {
		var el = element,
			queue = [],
			pointer = -1,
			self = this,
			run = false;

		self.start = function() {
			run = true;

			self.next();
		};

		self.next = function() {
			if ( pointer < queue.length-1 ) {
				pointer++;
			} else {
				pointer = 0;
			}

			var step = queue[pointer];

			if ( step.type == 'animation' ) {
				el.animate(
					step.ops,
					step.duration,
					step.easing,
					function() {
						self.next();
					}
				);
			} else {
				step.action();

				self.next();
			}
		};

		self.animate = function( ops, duration, easing ) {
			return self.enqueue(
				{
					type: 'animation',
					ops: ops,
					duration: duration,
					easing: easing
				}
			);
		};

		self.action = function( callback ) {
			return self.enqueue(
				{
					type: 'action',
					action: callback
				}
			);
		};

		self.enqueue = function( object )
		{
			queue.push(object);

			if ( run == false ) self.start();

			return self;
		}
	};

	this.get = function( el ) {
		return new tween(el);
	};
}
]
);
<commit_msg>flipping the text on object flip for lastebil<commit_after>var teammoldeApp = angular.module(
	"teammoldeApp",
	[
		'ngAnimate', 'ui.router'
	]
);

teammoldeApp
.config(
[
'$stateProvider', '$urlRouterProvider', '$sceProvider',
function ($stateProvider, $urlRouterProvider, $sceProvider)
{
	$sceProvider.enabled(false);

	$urlRouterProvider
		.otherwise('/');

	$stateProvider
		.state('home', {
			url: '/',
			views: {
				"main": {
					templateUrl: '/partials/home.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('priser', {
			url: '/priser',
			views: {
				"main": {
					templateUrl: '/partials/priser.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('larere', {
			url: '/larere',
			views: {
				"main": {
					templateUrl: '/partials/laerere.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('bestill', {
			url: '/bestill',
			views: {
				"main": {
					templateUrl: '/partials/bestill.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('elevside', {
			url: '/elevside',
			views: {
				"main": {
					templateUrl: '/partials/elevside.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('manedensbestatt', {
			url: '/manedensbestatt',
			views: {
				"main": {
					templateUrl: '/partials/manedensbestatt.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})

		.state('kontakt', {
			abstract: true,
			url: '/kontakt',
			views: {
				"main": {
					templateUrl: '/partials/kontakt.html'
				},
				"header": {
					templateUrl: '/partials/header.html'
				}
			}
		})
	;

}
]
);

teammoldeApp
.filter('bstableizer',
function () {
	return function ( markup ) {
		return markup.replace('
', '
');
	};
}
);

teammoldeApp
.controller('homeCtrl',
[
'$scope', 'bgSVG',
function($scope, bgSVG) {
	bgSVG.init().then(function(){
		bgSVG.go();
	});
}
]
);

teammoldeApp
.controller('PriserCtrl',
[
'$scope', 'wpData', 'bgSVG',
function($scope, wpData, bgSVG) {
	$scope.pricelist = '';

	wpData.getPage('priser')
		.then(function(html) {
			$scope.pricelist = html;
		});

	//bgSVG.blur(true);
}
]
);

teammoldeApp
.service('wpData',
[
'$q', '$http',
function ( $q, $http )
{
	this.getPage = function( url ) {
		var deferred = $q.defer();

		$http.get('wordpress/' + url + '/?json=1', {cache: true})
			.success(function(result) {
				deferred.resolve(result.page.content);
			})
			.error(function(){
				deferred.reject();
			});

		return deferred.promise;
	};
}
]
);

teammoldeApp
.service('bgSVG',
[
'$q', 'Tween',
function ( $q, Tween )
{
	var s,
		objects = {},
		self = this;

	this.init = function() {
		var deferred = $q.defer();

		s = Snap("#background");

		Snap.load("assets/svg/background.svg", function (f) {
			s.append(f);

			objects.cloud_left = Snap(s).select('#cloud-left');
			objects.cloud_right = Snap(s).select('#cloud-right');

			objects.cloud_left.attr({transform: 'translate(400,0)'});
			objects.cloud_right.attr({transform: 'translate(-400,0)'});

			objects.personbil = Snap(s).select('#personbil');

			objects.lett_lastebil = Snap(s).select('#lett-lastebil');

			objects.lastebil = Snap(s).select('#lastebil');

			objects.buss = Snap(s).select('#buss');

			deferred.resolve();
		});

		return deferred.promise;
	};

	this.go = function() {
		Tween.get(objects.cloud_left)
			.animate({transform: 'translate(600,0)'},10000, mina.easeinout)
			.animate({transform: 'translate(1000,0)'},7500, mina.easeinout)
			.animate({transform: 'translate(1800,0)'},7500, mina.easeinout)
			.animate({transform: 'translate(2200,0)'},7500, mina.easeinout)
			.animate({transform: 'translate(2600,0)'},7500, mina.easeinout)
			.action(function(){
				objects.cloud_left.attr({transform: 'translate(0,0)'});
			})
		;

		Tween.get(objects.cloud_right)
			.animate({transform: 'translate(-600,0)'},5000, mina.easeinout)
			.animate({transform: 'translate(-1000,0)'},10000, mina.easeinout)
			.animate({transform: 'translate(-1500,0)'},7500, mina.easeinout)
			.animate({transform: 'translate(-2200,0)'},10000, mina.easeinout)
			.animate({transform: 'translate(-2600,0)'},7500, mina.easeinout)
			.action(function(){
				objects.cloud_right.attr({transform: 'translate(0,0)'});
			})
		;

		Tween.get(objects.personbil)
			.animate({transform: 'translate(700,0)'}, 2000, mina.easeinout)
			.animate({transform: 'translate(700,0)'}, 500, mina.linear)
			.animate({transform: 'translate(900,0)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(900,0)'}, 500, mina.linear)
			.animate({transform: 'translate(1300,0)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(1300,0)'}, 500, mina.linear)
			.animate({transform: 'translate(1600,0)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(1850,0) scale(-1, 1)'}, 1000, mina.easeinout)
			.animate({transform: 'translate(1600,0) scale(-1, 1)'}, 2500, mina.linear)
			.animate({transform: 'translate(1300,0) scale(-1, 1)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(700,0) scale(-1, 1)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(250,0) scale(-1, 1)'}, 1000, mina.easeinout)
			.animate({transform: 'translate(0,0) scale(1, 1)'}, 1000, mina.easeinout)
		;

		Tween.get(objects.lett_lastebil)
			.animate({transform: 'translate(-200,0)'}, 3000, mina.easeinout)
			.animate({transform: 'translate(-200,0)'}, 500, mina.linear)
			.animate({transform: 'translate(-400,0)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(-400,0)'}, 500, mina.linear)
			.animate({transform: 'translate(-800,0)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(2000,0) scale(-1, 1)'}, 2000, mina.easeinout)
			.animate({transform: 'translate(2000,0) scale(-1, 1)'}, 2500, mina.linear)
			.animate({transform: 'translate(2400,0) scale(-1, 1)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(3000,0) scale(-1, 1)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(3200,0) scale(-1, 1)'}, 1000, mina.easeinout)
			.animate({transform: 'translate(800,0) scale(1, 1)'}, 1000, mina.easeinout)
		;

		Tween.get(objects.lastebil)
			.animate({transform: 'translate(-200,0)'}, 3000, mina.easeinout)
			.animate({transform: 'translate(-200,0)'}, 100, mina.linear)
			.animate({transform: 'translate(-800,0)'}, 9000, mina.easeinout)
			.animate({transform: 'translate(2000,0) scale(-1, 1)'}, 2000, mina.easeinout)
			.action(function(){
				Snap(s).select('#lastebil text').attr({transform:'translate(1640,0) scale(-1, 1)'});
			})
			.animate({transform: 'translate(2000,0) scale(-1, 1)'}, 2500, mina.linear)
			.animate({transform: 'translate(2400,0) scale(-1, 1)'}, 5000, mina.easeinout)
			.animate({transform: 'translate(3000,0) scale(-1, 1)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(3200,0) scale(-1, 1)'}, 1000, mina.easeinout)
			.action(function(){
				Snap(s).select('#lastebil text').attr({transform:'translate(0,0) scale(1, 1)'});
			})
			.animate({transform: 'translate(800,0) scale(1, 1)'}, 1000, mina.easeinout)
		;

		Tween.get(objects.buss)
			.animate({transform: 'translate(0,0)'}, 2500, mina.linear)
			.animate({transform: 'translate(-200,0)'}, 3000, mina.easeinout)
			.animate({transform: 'translate(-200,0)'}, 500, mina.linear)
			.animate({transform: 'translate(-400,0)'}, 4000, mina.easeinout)
			.animate({transform: 'translate(-400,0)'}, 500, mina.linear)
			.animate({transform: 'matrix(0.8660254,0.5,-0.5,0.8660254,-24.308937,-698.29248)'}, 5000, mina.easeinout)
			.animate({transform: 'matrix(0.94967542,0.31323569,-0.31323569,0.94967542,-374.13056,-520.01597)'}, 5000, mina.linear)
			.animate({transform: 'matrix(0.98814356,0.15353273,-0.15353273,0.98814356,-656.74677,-340.16701)'}, 2500, mina.linear)
			.animate({transform: 'translate(-897,-131)'}, 2500, mina.linear)
			.action(function(){
				objects.buss.attr({transform: 'translate(0,0)'});
			})
		;
	};

	this.blur = function( blur ) {
		s.attr({
			filter: blur ? f : null
		});
	};
}
]
);

teammoldeApp
.service('Tween',
[
'$q',
function ( $q )
{
	var tween = function( element ) {
		var el = element,
			queue = [],
			pointer = -1,
			self = this,
			run = false;

		self.start = function() {
			run = true;

			self.next();
		};

		self.next = function() {
			if ( pointer < queue.length-1 ) {
				pointer++;
			} else {
				pointer = 0;
			}

			var step = queue[pointer];

			if ( step.type == 'animation' ) {
				el.animate(
					step.ops,
					step.duration,
					step.easing,
					function() {
						self.next();
					}
				);
			} else {
				step.action();

				self.next();
			}
		};

		self.animate = function( ops, duration, easing ) {
			return self.enqueue(
				{
					type: 'animation',
					ops: ops,
					duration: duration,
					easing: easing
				}
			);
		};

		self.action = function( callback ) {
			return self.enqueue(
				{
					type: 'action',
					action: callback
				}
			);
		};

		self.enqueue = function( object )
		{
			queue.push(object);

			if ( run == false ) self.start();

			return self;
		}
	};

	this.get = function( el ) {
		return new tween(el);
	};
}
]
);
<|endoftext|>