From 6166c15c867421b57f7da00d21e52e85add2bd65 Mon Sep 17 00:00:00 2001
From: rclations
Date: Thu, 22 Jun 2017 17:04:23 -0400
Subject: [PATCH 01/41] working on boilerplate in subfolder
---
.bowerrc | 3 -
.gitignore | 3 -
boilerplate/.bowerrc | 3 +
boilerplate/.editorconfig | 24 +
boilerplate/.eslintrc.js | 78 +++
boilerplate/.eslintrc.json | 171 +++++
boilerplate/.gitignore | 80 +++
boilerplate/.sass-lint.yml | 142 ++++
boilerplate/.travis.yml | 23 +
boilerplate/.yo-rc.json | 19 +
boilerplate/Dockunit.json | 157 +++++
boilerplate/Gulpfile.js | 360 ++++++++++
readme.txt => boilerplate/README.md | 43 +-
boilerplate/assets/README.md | 6 +
boilerplate/assets/css/sass/styles.scss | 22 +
boilerplate/assets/js/jquery.dfp.js | 653 ++++++++++++++++++
boilerplate/assets/js/jquery.dfp.min.js | 8 +
boilerplate/assets/repo/README.md | 6 +
boilerplate/bin/install-wp-tests.sh | 113 +++
bower.json => boilerplate/bower.json | 0
{docs => boilerplate/docs}/img/create-key.png | Bin
.../docs}/img/custom-criteria.png | Bin
{docs => boilerplate/docs}/img/dfw.png | Bin
{docs => boilerplate/docs}/img/key-values.png | Bin
{docs => boilerplate/docs}/img/name-key.png | Bin
.../docs}/img/network-code.png | Bin
{docs => boilerplate/docs}/img/targeting.png | Bin
{docs => boilerplate/docs}/img/widget.png | Bin
boilerplate/doubleclick-for-wordpress.php | 373 ++++++++++
boilerplate/includes/README.md | 6 +
boilerplate/languages | 21 +
boilerplate/package.json | 57 ++
boilerplate/phpcs.xml | 16 +
boilerplate/phpunit.xml | 14 +
release.sh => boilerplate/release.sh | 0
boilerplate/tests/bootstrap.php | 35 +
boilerplate/tests/test-base.php | 36 +
css/dfp.css | 15 -
docs/Colophon.md | 9 -
docs/Developer-API.md | 105 ---
docs/Targeting.md | 91 ---
docs/index.md | 51 --
readme.md | 5 -
43 files changed, 2451 insertions(+), 297 deletions(-)
delete mode 100644 .bowerrc
delete mode 100644 .gitignore
create mode 100644 boilerplate/.bowerrc
create mode 100644 boilerplate/.editorconfig
create mode 100644 boilerplate/.eslintrc.js
create mode 100644 boilerplate/.eslintrc.json
create mode 100644 boilerplate/.gitignore
create mode 100644 boilerplate/.sass-lint.yml
create mode 100644 boilerplate/.travis.yml
create mode 100644 boilerplate/.yo-rc.json
create mode 100644 boilerplate/Dockunit.json
create mode 100644 boilerplate/Gulpfile.js
rename readme.txt => boilerplate/README.md (67%)
create mode 100644 boilerplate/assets/README.md
create mode 100644 boilerplate/assets/css/sass/styles.scss
create mode 100644 boilerplate/assets/js/jquery.dfp.js
create mode 100644 boilerplate/assets/js/jquery.dfp.min.js
create mode 100644 boilerplate/assets/repo/README.md
create mode 100644 boilerplate/bin/install-wp-tests.sh
rename bower.json => boilerplate/bower.json (100%)
rename {docs => boilerplate/docs}/img/create-key.png (100%)
rename {docs => boilerplate/docs}/img/custom-criteria.png (100%)
rename {docs => boilerplate/docs}/img/dfw.png (100%)
rename {docs => boilerplate/docs}/img/key-values.png (100%)
rename {docs => boilerplate/docs}/img/name-key.png (100%)
rename {docs => boilerplate/docs}/img/network-code.png (100%)
rename {docs => boilerplate/docs}/img/targeting.png (100%)
rename {docs => boilerplate/docs}/img/widget.png (100%)
create mode 100644 boilerplate/doubleclick-for-wordpress.php
create mode 100644 boilerplate/includes/README.md
create mode 100644 boilerplate/languages
create mode 100644 boilerplate/package.json
create mode 100644 boilerplate/phpcs.xml
create mode 100644 boilerplate/phpunit.xml
rename release.sh => boilerplate/release.sh (100%)
create mode 100644 boilerplate/tests/bootstrap.php
create mode 100644 boilerplate/tests/test-base.php
delete mode 100644 css/dfp.css
delete mode 100644 docs/Colophon.md
delete mode 100644 docs/Developer-API.md
delete mode 100644 docs/Targeting.md
delete mode 100644 docs/index.md
delete mode 100644 readme.md
diff --git a/.bowerrc b/.bowerrc
deleted file mode 100644
index 107d1e8..0000000
--- a/.bowerrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "directory": "js/vendor"
-}
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 8006366..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-site/*
-release/*
-js/vendor/*
diff --git a/boilerplate/.bowerrc b/boilerplate/.bowerrc
new file mode 100644
index 0000000..0eac082
--- /dev/null
+++ b/boilerplate/.bowerrc
@@ -0,0 +1,3 @@
+{
+ "directory": "assets/bower"
+}
\ No newline at end of file
diff --git a/boilerplate/.editorconfig b/boilerplate/.editorconfig
new file mode 100644
index 0000000..8a9fde0
--- /dev/null
+++ b/boilerplate/.editorconfig
@@ -0,0 +1,24 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+# Matches multiple files with brace expansion notation
+# Set default charset
+[*.{html,js,php,css,scss}]
+charset = utf-8
+
+# 4 space indentation
+[*.{html,js,php,css,scss}]
+indent_style = tab
+indent_size = 4
+
+# Matches the exact files
+[{package.json,bower.json,.bowerrc,.eslintrc,.travis.yml,.sass-lint.yml,phpcs.xml}]
+indent_style = space
+indent_size = 2
diff --git a/boilerplate/.eslintrc.js b/boilerplate/.eslintrc.js
new file mode 100644
index 0000000..c1e5082
--- /dev/null
+++ b/boilerplate/.eslintrc.js
@@ -0,0 +1,78 @@
+module.exports = {
+ "env": {
+ "browser": true,
+ "jquery": true,
+ "es6": true,
+ },
+ "extends": "wordpress",
+ "installedESLint": true,
+ "plugins": [],
+ "rules": {
+ // Enforce spacing inside array brackets
+ 'array-bracket-spacing': ['error', 'always'],
+ // Enforce one true brace style
+ 'brace-style': 'error',
+ // Require camel case names
+ 'camelcase': ['error', {
+ properties: 'always'
+ }],
+ // Disallow or enforce trailing commas
+ 'comma-dangle': ['error', 'never'],
+ // Enforce spacing before and after comma
+ 'comma-spacing': 'error',
+ // Enforce one true comma style
+ 'comma-style': ['error', 'last'],
+ // Encourages use of dot notation whenever possible
+ 'dot-notation': ['error', {
+ allowKeywords: true,
+ allowPattern: '^[a-z]+(_[a-z]+)+$'
+ }],
+ // Enforce newline at the end of file, with no multiple empty lines
+ 'eol-last': 'error',
+ // Require or disallow spacing between function identifiers and their invocations
+ 'func-call-spacing': 'off',
+ // Enforces spacing between keys and values in object literal properties
+ 'key-spacing': ['error', {
+ beforeColon: false,
+ afterColon: true
+ }],
+ // Enforce spacing before and after keywords
+ 'keyword-spacing': 'error',
+ // Disallow mixed "LF" and "CRLF" as linebreaks
+ 'linebreak-style': ['error', 'unix'],
+ // Enforces empty lines around comments
+ 'lines-around-comment': ['error', {
+ beforeLineComment: true
+ }],
+ // Disallow mixed spaces and tabs for indentation
+ 'no-mixed-spaces-and-tabs': 'error',
+ // Disallow use of multiline strings
+ 'no-multi-str': 'error',
+ // Disallow multiple empty lines
+ 'no-multiple-empty-lines': 'error',
+ // Disallow use of the with statement
+ 'no-with': 'error',
+ // Require or disallow an newline around variable declarations
+ 'one-var-declaration-per-line': ['error', 'initializations'],
+ // Enforce operators to be placed before or after line breaks
+ 'operator-linebreak': ['error', 'after'],
+ // Require or disallow use of semicolons instead of ASI
+ 'semi': ['error', 'always'],
+ // Require or disallow space before blocks
+ 'space-before-blocks': ['error', 'always'],
+ // Require or disallow space before function opening parenthesis
+ 'space-before-function-paren': ['error', 'never'],
+ // Require or disallow space before blocks
+ 'space-in-parens': ['error', 'always', {exceptions: ['{}', '[]']}],
+ // Require spaces around operators
+ 'space-infix-ops': 'error',
+ // Require or disallow spaces before/after unary operators (words on by default, nonwords)
+ 'space-unary-ops': ['error', {
+ overrides: {'!': true}
+ }],
+ // Requires to declare all vars on top of their containing scope
+ 'vars-on-top': 'error',
+ // Require or disallow Yoda conditions
+ 'yoda': ['error', 'always']
+ }
+}
diff --git a/boilerplate/.eslintrc.json b/boilerplate/.eslintrc.json
new file mode 100644
index 0000000..2d2951e
--- /dev/null
+++ b/boilerplate/.eslintrc.json
@@ -0,0 +1,171 @@
+{
+ "globals": {
+ },
+
+ "env": {
+ "browser": true,
+ "commonjs": true,
+ "jquery": true
+ },
+
+ "parserOptions": {
+ "ecmaVersion": 6,
+ "sourceType": "module",
+ "ecmaFeatures": {
+ "jsx": true,
+ "impliedStrict": true
+ }
+ },
+
+ "rules": {
+ // Possible Errors
+ "comma-dangle": 2,
+ "no-cond-assign": 2,
+ "no-console": 1,
+ "no-constant-condition": 2,
+ "no-control-regex": 2,
+ "no-debugger": 1,
+ "no-dupe-args": 2,
+ "no-dupe-keys": 2,
+ "no-duplicate-case": 2,
+ "no-empty-character-class": 2,
+ "no-empty": 2,
+ "no-ex-assign": 2,
+ "no-extra-boolean-cast": 2,
+ "no-extra-parens": 2,
+ "no-extra-semi": 2,
+ "no-func-assign": 2,
+ "no-inner-declarations": 2,
+ "no-invalid-regexp": 2,
+ "no-irregular-whitespace": 2,
+ "no-negated-in-lhs": 2,
+ "no-obj-calls": 2,
+ "no-regex-spaces": 2,
+ "no-sparse-arrays": 2,
+ "no-unreachable": 2,
+ "use-isnan": 2,
+ "valid-jsdoc": 2,
+ "valid-typeof": 2,
+ "no-unexpected-multiline": 2,
+ // Best Practices
+ "accessor-pairs": 2,
+ "block-scoped-var": 2,
+ "complexity": 2,
+ "consistent-return": 2,
+ "curly": 2,
+ "default-case": 2,
+ "dot-notation": 2,
+ "dot-location": [2, "property"],
+ "eqeqeq": 2,
+ "guard-for-in": 2,
+ "no-alert": 2,
+ "no-caller": 2,
+ "no-div-regex": 2,
+ "no-else-return": 2,
+ "no-eq-null": 2,
+ "no-eval": 2,
+ "no-extend-native": 2,
+ "no-extra-bind": 2,
+ "no-fallthrough": 2,
+ "no-floating-decimal": 2,
+ "no-implied-eval": 2,
+ "no-iterator": 2,
+ "no-labels": 2,
+ "no-lone-blocks": 2,
+ "no-loop-func": 2,
+ "no-multi-spaces": [2, { "exceptions": { "VariableDeclarator": true } }],
+ "no-multi-str": 2,
+ "no-native-reassign": 2,
+ "no-new-func": 2,
+ "no-new-wrappers": 2,
+ "no-new": 2,
+ "no-octal-escape": 2,
+ "no-octal": 2,
+ "no-process-env": 2,
+ "no-proto": 2,
+ "no-redeclare": 2,
+ "no-return-assign": 2,
+ "no-script-url": 2,
+ "no-self-compare": 2,
+ "no-sequences": 2,
+ "no-throw-literal": 2,
+ "no-unused-expressions": 2,
+ "no-useless-call": 2,
+ "no-useless-concat": 2,
+ "no-void": 2,
+ "no-warning-comments": 2,
+ "no-with": 2,
+ "radix": 2,
+ "vars-on-top": 2,
+ "wrap-iife": 2,
+ "yoda": [1, "always"],
+ // Strict Mode
+ "strict": 2,
+ // Variables
+ "no-catch-shadow": 2,
+ "no-delete-var": 2,
+ "no-label-var": 2,
+ "no-shadow-restricted-names": 2,
+ "no-shadow": 2,
+ "no-undef-init": 2,
+ "no-undef": 2,
+ "no-undefined": 2,
+ "no-unused-vars": 2,
+ "no-use-before-define": 2,
+ // Stylistic Issues
+ "array-bracket-spacing": [2, "always"],
+ "block-spacing": 2,
+ "brace-style": 2,
+ "camelcase": 2,
+ "comma-spacing": [2, {"before": false, "after": true}],
+ "comma-style": [2, "last"],
+ "consistent-this": 2,
+ "eol-last": 2,
+ "func-style": 2,
+ "id-match": 2,
+ "indent": [2, "tab", {"SwitchCase": 1} ],
+ "key-spacing": [1, { "align": "value" }],
+ "lines-around-comment": [2, { "beforeBlockComment": true, "allowBlockStart": true , "allowObjectStart": true }],
+ "linebreak-style": 2,
+ "max-nested-callbacks": 2,
+ "new-cap": 2,
+ "new-parens": 2,
+ "newline-after-var": 2,
+ "no-array-constructor": 2,
+ "no-continue": 2,
+ "no-inline-comments": 2,
+ "no-lonely-if": 2,
+ "no-mixed-spaces-and-tabs": 2,
+ "no-multiple-empty-lines": 2,
+ "no-nested-ternary": 2,
+ "no-new-object": 2,
+ "no-spaced-func": 2,
+ "no-trailing-spaces": 2,
+ "no-underscore-dangle": 2,
+ "no-unneeded-ternary": 2,
+ "object-curly-spacing": [2, "always"],
+ "one-var": 2,
+ "operator-assignment": 2,
+ "operator-linebreak": 2,
+ "padded-blocks": [2, "never"],
+ "quote-props": [2, "as-needed"],
+ "quotes": [2, "single"],
+ "semi-spacing": 2,
+ "semi": [2, "always"],
+ "keyword-spacing": 1,
+ "space-before-blocks": 2,
+ "space-before-function-paren": [2, "never"],
+ "space-in-parens": [2, "always"],
+ "space-infix-ops": 2,
+ "space-unary-ops": [1, { "words": true, "nonwords": true }],
+ "spaced-comment": 2,
+ "wrap-regex": 2,
+ // Legacy
+ "max-depth": 2,
+ "max-len": [1, 100, 4],
+ "max-params": [2, 4],
+ "max-statements": 1,
+ "no-bitwise": 2,
+ "no-plusplus": 2
+ }
+}
diff --git a/boilerplate/.gitignore b/boilerplate/.gitignore
new file mode 100644
index 0000000..ddbb21f
--- /dev/null
+++ b/boilerplate/.gitignore
@@ -0,0 +1,80 @@
+# Node/npm
+node_modules/
+npm-debug.log
+.grunt
+.sass-cache
+
+# OSX
+.DS_Store
+.AppleDouble
+.LSOverride
+.Spotlight-V100
+.Trashes
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+
+# Vim
+[._]*.s[a-w][a-z]
+[._]s[a-w][a-z]
+*.un~
+Session.vim
+.netrwhist
+*~
+
+### Bower ###
+bower_components
+.bower-cache
+.bower-registry
+.bower-tmp
+
+# Logs
+logs
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
+node_modules
+
+
+
+# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
+# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
+# composer.lock
+
+
+# Other, add your own ignored things here.
+.idea/
+release
+site
+js/vendor
diff --git a/boilerplate/.sass-lint.yml b/boilerplate/.sass-lint.yml
new file mode 100644
index 0000000..c1fc5f3
--- /dev/null
+++ b/boilerplate/.sass-lint.yml
@@ -0,0 +1,142 @@
+# Sample Configs
+# - https://github.com/sasstools/sass-lint/blob/develop/docs/sass-lint.yml
+# - https://github.com/sasstools/gulp-sass-lint/blob/master/tests/.sass-lint.yml
+
+# Sass Lint Rules
+# - https://github.com/sasstools/sass-lint/tree/develop/docs/rules
+
+# Severity
+# - 0: turns rule off
+# - 1: set as a warning
+# - 2: set to error
+
+# File Options
+files:
+ ignore:
+ - 'sass/vendor/**/*.scss'
+ - 'sass/tests/**/*.scss'
+ - 'bourbon/app/**/*.scss'
+ - 'bourbon-neat/app/**/*.scss'
+
+# Rule Configuration
+rules:
+ # Extends
+ placeholder-in-extend: 0
+
+ # Mixins
+ mixins-before-declarations:
+ - 1
+ -
+ exclude: ['media'] # except @include media();
+
+ # Line Spacing
+ empty-line-between-blocks:
+ - 1
+ -
+ allow-single-line-rulesets: false
+
+ # Disallows
+ no-color-literals:
+ - 1
+ -
+ allow-rgba: true
+ no-debug: 0
+ no-ids: 0
+ no-mergeable-selectors: 0
+ no-qualifying-elements:
+ - 1
+ -
+ allow-element-with-attribute: true
+ allow-element-with-class: false
+ allow-element-with-id: false
+ no-vendor-prefixes: 0
+ no-warn: 0
+
+ # Nesting
+ force-attribute-nesting: 0
+ force-element-nesting: 0
+ force-pseudo-nesting: 0
+
+ # Name Formats
+ function-name-format:
+ - 1
+ -
+ convention-explanation: Please use hyphenated lowercase for function names. Also, you may use a leading underscore if you prefer.
+ mixin-name-format:
+ - 1
+ -
+ convention-explanation: Please use hyphenated lowercase for mixin names. Also, you may use a leading underscore if you prefer.
+ placeholder-name-format:
+ - 1
+ -
+ convention-explanation: Please use hyphenated lowercase for placeholder names. Also, you may use a leading underscore if you prefer.
+ variable-name-format:
+ - 1
+ -
+ allow-leading-underscore: false
+ convention-explanation: Please use hyphenated lowercase for variable names. No leading underscore is allowed.
+
+ # Style Guide
+ attribute-quotes: 1
+ border-zero: 0
+ brace-style:
+ - 1
+ -
+ style: 1tbs
+ allow-single-line: false
+ class-name-format:
+ - 1
+ -
+ allow-leading-underscore: false
+ convention-explanation: Please use hypenated lowercase for class names, and without a leading underscore. If you find a WordPress core condition that conflicts with this convention feel free to modify and extend the ignore option.
+ ignore: ['current_page_item', 'widget_search'] # ignore selectors declared by WordPress
+
+ empty-args: 0
+ hex-length: 1
+ hex-notation: 1
+ id-name-format:
+ - 1
+ -
+ convention-explanation: Please try to use hyphenated lowercase ID name format. If overriding a plugin that does not use this format then please ignore or extend the list of ignore option.
+ indentation:
+ - 1
+ -
+ size: tab
+ leading-zero:
+ - 1
+ -
+ include: true
+
+ nesting-depth:
+ - 1
+ -
+ max-depth: 3
+
+ property-units:
+ - 1
+ -
+ per-property: { width: ['rem', 'vw'], height: ['rem', 'vh'], margin: ['rem'], padding: ['rem'] }
+
+ quotes:
+ - 1
+ -
+ style: double
+
+ shorthand-values:
+ - 1
+ -
+ allowed-shorthands:
+ - 1
+ - 2
+
+ # Inner Spacing
+ space-between-parens: 0
+
+ # Final Items
+ final-newline: 0
+
+ no-misspelled-properties:
+ - 1
+ -
+ 'extra-properties':
+ - '-webkit-overflow-scrolling'
diff --git a/boilerplate/.travis.yml b/boilerplate/.travis.yml
new file mode 100644
index 0000000..cbef1ee
--- /dev/null
+++ b/boilerplate/.travis.yml
@@ -0,0 +1,23 @@
+language: php
+
+notifications:
+ email:
+ on_success: never
+ on_failure: change
+
+php:
+ - 5.3
+ - 5.5
+
+env:
+ - WP_VERSION=latest WP_MULTISITE=0
+
+matrix:
+ include:
+ - php: 5.3
+ env: WP_VERSION=latest WP_MULTISITE=1
+
+before_script:
+ - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
+
+script: phpunit
diff --git a/boilerplate/.yo-rc.json b/boilerplate/.yo-rc.json
new file mode 100644
index 0000000..08fb816
--- /dev/null
+++ b/boilerplate/.yo-rc.json
@@ -0,0 +1,19 @@
+{
+ "generator-plugin-wp": {
+ "name": "DoubleClick for WordPress",
+ "homepage": "https://labs.inn.org",
+ "description": "Serve DoubleClick ads natively in WordPress. Built to make serving and targeting responsive ads easy.",
+ "version": "0.2.1",
+ "author": "innlabs, willhaynes24",
+ "authoremail": "labs@inn.org",
+ "authorurl": "https://labs.inn.org",
+ "license": "GPLv2",
+ "slug": "doubleclick-for-wordpress",
+ "classname": "DoubleClick_For_WordPress",
+ "mainclassname": "DoubleClick_For_WordPress",
+ "classprefix": "DCFWP_",
+ "prefix": "doubleclick_for_wordpress",
+ "year": 2017,
+ "currentVersionWP": "4.7.2"
+ }
+}
\ No newline at end of file
diff --git a/boilerplate/Dockunit.json b/boilerplate/Dockunit.json
new file mode 100644
index 0000000..047a815
--- /dev/null
+++ b/boilerplate/Dockunit.json
@@ -0,0 +1,157 @@
+{
+ "containers":[
+ {
+ "prettyName":"PHP 7.0 FPM WordPress Latest",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test root '' localhost"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 7.0 FPM WordPress 4.7",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.7"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 7.0 FPM WordPress 4.6",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.6"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 7.0 FPM WordPress 4.5",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.5"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 7.0 FPM WordPress 4.4",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.4"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 7.0 FPM WordPress 4.3",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-7.0-rc-4-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.3"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.6 FPM WordPress Latest",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.6 FPM WordPress 4.7",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.7"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.6 FPM WordPress 4.6",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.6"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.6 FPM WordPress 4.5",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.5"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.6 FPM WordPress 4.4",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.4"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.6 FPM WordPress 4.3",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.6-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.3"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.2 FPM WordPress 4.7",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.7"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.2 FPM WordPress 4.6",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.6"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.2 FPM WordPress 4.5",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.5"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.2 FPM WordPress 4.4",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.4"
+ ],
+ "testCommand":"phpunit"
+ },
+ {
+ "prettyName":"PHP 5.2 FPM WordPress 4.3",
+ "image":"dockunit/prebuilt-images:php-mysql-phpunit-wordpress-5.2-fpm",
+ "beforeScripts":[
+ "service mysql start",
+ "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 4.3"
+ ],
+ "testCommand":"phpunit"
+ }
+ ]
+}
diff --git a/boilerplate/Gulpfile.js b/boilerplate/Gulpfile.js
new file mode 100644
index 0000000..608f7f7
--- /dev/null
+++ b/boilerplate/Gulpfile.js
@@ -0,0 +1,360 @@
+// Require our dependencies
+const autoprefixer = require( 'autoprefixer' );
+const babel = require( 'gulp-babel' );
+const bourbon = require( 'bourbon' ).includePaths;
+const browserSync = require( 'browser-sync' );
+const cheerio = require( 'gulp-cheerio' );
+const concat = require( 'gulp-concat' );
+const cssnano = require( 'gulp-cssnano' );
+const del = require( 'del' );
+const eslint = require( 'gulp-eslint' );
+const gulp = require( 'gulp' );
+const gutil = require( 'gulp-util' );
+const imagemin = require( 'gulp-imagemin' );
+const mqpacker = require( 'css-mqpacker' );
+const neat = require( 'bourbon-neat' ).includePaths;
+const notify = require( 'gulp-notify' );
+const plumber = require( 'gulp-plumber' );
+const postcss = require( 'gulp-postcss' );
+const reload = browserSync.reload;
+const rename = require( 'gulp-rename' );
+const sass = require( 'gulp-sass' );
+const sassLint = require( 'gulp-sass-lint' );
+const sort = require( 'gulp-sort' );
+const sourcemaps = require( 'gulp-sourcemaps' );
+const spritesmith = require( 'gulp.spritesmith' );
+const svgmin = require( 'gulp-svgmin' );
+const svgstore = require( 'gulp-svgstore' );
+const uglify = require( 'gulp-uglify' );
+const wpPot = require( 'gulp-wp-pot' );
+
+// Set assets paths.
+const paths = {
+ 'css': [ './*.css', '!*.min.css' ],
+ 'icons': 'assets/images/svg-icons/*.svg',
+ 'images': [ 'assets/images/*', '!assets/images/*.svg' ],
+ 'php': [ './*.php', './**/*.php' ],
+ 'sass': 'assets/css/sass/*.scss',
+ 'concat_scripts': 'assets/scripts/concat/*.js',
+ 'scripts': [ 'assets/scripts/*.js', 'assets/js/*.js', '!assets/scripts/*.min.js' ],
+ 'sprites': 'assets/images/sprites/*.png'
+};
+
+/**
+ * Handle errors and alert the user.
+ */
+function handleErrors () {
+ const args = Array.prototype.slice.call( arguments );
+
+ notify.onError( {
+ 'title': 'Task Failed [<%= error.message %>',
+ 'message': 'See console.',
+ 'sound': 'Sosumi' // See: https://github.com/mikaelbr/node-notifier#all-notification-options-with-their-defaults
+ } ).apply( this, args );
+
+ gutil.beep(); // Beep 'sosumi' again.
+
+ // Prevent the 'watch' task from stopping.
+ this.emit( 'end' );
+}
+
+/**
+ * Delete style.css and style.min.css before we minify and optimize
+ */
+gulp.task( 'clean:styles', () =>
+ del( [ 'style.css', 'style.min.css' ] )
+);
+
+/**
+ * Compile Sass and run stylesheet through PostCSS.
+ *
+ * https://www.npmjs.com/package/gulp-sass
+ * https://www.npmjs.com/package/gulp-postcss
+ * https://www.npmjs.com/package/gulp-autoprefixer
+ * https://www.npmjs.com/package/css-mqpacker
+ */
+gulp.task( 'postcss', [ 'clean:styles' ], () =>
+ gulp.src( 'assets/sass/*.scss', paths.css )
+
+ // Deal with errors.
+ .pipe( plumber( {'errorHandler': handleErrors} ) )
+
+ // Wrap tasks in a sourcemap.
+ .pipe( sourcemaps.init() )
+
+ // Compile Sass using LibSass.
+ .pipe( sass( {
+ 'includePaths': [].concat( bourbon, neat ),
+ 'errLogToConsole': true,
+ 'outputStyle': 'expanded' // Options: nested, expanded, compact, compressed
+ } ) )
+
+ // Parse with PostCSS plugins.
+ .pipe( postcss( [
+ autoprefixer( {
+ 'browsers': [ 'last 2 version' ]
+ } ),
+ mqpacker( {
+ 'sort': true
+ } )
+ ] ) )
+
+ // Create sourcemap.
+ .pipe( sourcemaps.write() )
+
+ // Create style.css.
+ .pipe( gulp.dest( './' ) )
+ .pipe( browserSync.stream() )
+);
+
+/**
+ * Minify and optimize style.css.
+ *
+ * https://www.npmjs.com/package/gulp-cssnano
+ */
+gulp.task( 'cssnano', [ 'postcss' ], () =>
+ gulp.src( 'style.css' )
+ .pipe( plumber( {'errorHandler': handleErrors} ) )
+ .pipe( cssnano( {
+ 'safe': true // Use safe optimizations.
+ } ) )
+ .pipe( rename( 'style.min.css' ) )
+ .pipe( gulp.dest( './' ) )
+ .pipe( browserSync.stream() )
+);
+
+/**
+ * Delete the svg-icons.svg before we minify, concat.
+ */
+gulp.task( 'clean:icons', () =>
+ del( [ 'assets/images/svg-icons.svg' ] )
+);
+
+/**
+ * Minify, concatenate, and clean SVG icons.
+ *
+ * https://www.npmjs.com/package/gulp-svgmin
+ * https://www.npmjs.com/package/gulp-svgstore
+ * https://www.npmjs.com/package/gulp-cheerio
+ */
+gulp.task( 'svg', [ 'clean:icons' ], () =>
+ gulp.src( paths.icons )
+
+ // Deal with errors.
+ .pipe( plumber( {'errorHandler': handleErrors} ) )
+
+ // Minify SVGs.
+ .pipe( svgmin() )
+
+ // Add a prefix to SVG IDs.
+ .pipe( rename( {'prefix': 'icon-'} ) )
+
+ // Combine all SVGs into a single
+ .pipe( svgstore( {'inlineSvg': true} ) )
+
+ // Clean up the by removing the following cruft...
+ .pipe( cheerio( {
+ 'run': function ( $, file ) {
+ $( 'svg' ).attr( 'style', 'display:none' );
+ $( '[fill]' ).removeAttr( 'fill' );
+ $( 'path' ).removeAttr( 'class' );
+ },
+ 'parserOptions': {'xmlMode': true}
+ } ) )
+
+ // Save svg-icons.svg.
+ .pipe( gulp.dest( 'assets/images/' ) )
+ .pipe( browserSync.stream() )
+);
+
+/**
+ * Optimize images.
+ *
+ * https://www.npmjs.com/package/gulp-imagemin
+ */
+gulp.task( 'imagemin', () =>
+ gulp.src( paths.images )
+ .pipe( plumber( {'errorHandler': handleErrors} ) )
+ .pipe( imagemin( {
+ 'optimizationLevel': 5,
+ 'progressive': true,
+ 'interlaced': true
+ } ) )
+ .pipe( gulp.dest( 'assets/images' ) )
+);
+
+/**
+ * Delete the sprites.png before rebuilding sprite.
+ */
+gulp.task( 'clean:sprites', () => {
+ del( [ 'assets/images/sprites.png' ] )
+} );
+
+/**
+ * Concatenate images into a single PNG sprite.
+ *
+ * https://www.npmjs.com/package/gulp.spritesmith
+ */
+gulp.task( 'spritesmith', [ 'clean:sprites' ], () =>
+ gulp.src( paths.sprites )
+ .pipe( plumber( {'errorHandler': handleErrors} ) )
+ .pipe( spritesmith( {
+ 'imgName': 'sprites.png',
+ 'cssName': '../../assets/sass/base/_sprites.scss',
+ 'imgPath': 'assets/images/sprites.png',
+ 'algorithm': 'binary-tree'
+ } ) )
+ .pipe( gulp.dest( 'assets/images/' ) )
+ .pipe( browserSync.stream() )
+);
+
+/**
+ * Concatenate and transform JavaScript.
+ *
+ * https://www.npmjs.com/package/gulp-concat
+ * https://github.com/babel/gulp-babel
+ * https://www.npmjs.com/package/gulp-sourcemaps
+ */
+gulp.task( 'concat', () =>
+ gulp.src( paths.concat_scripts )
+
+ // Deal with errors.
+ .pipe( plumber(
+ {'errorHandler': handleErrors}
+ ) )
+
+ // Start a sourcemap.
+ .pipe( sourcemaps.init() )
+
+ // Convert ES6+ to ES2015.
+ .pipe( babel( {
+ presets: [ 'es2015' ]
+ } ) )
+
+ // Concatenate partials into a single script.
+ .pipe( concat( 'project.js' ) )
+
+ // Append the sourcemap to project.js.
+ .pipe( sourcemaps.write() )
+
+ // Save project.js
+ .pipe( gulp.dest( 'assets/scripts' ) )
+ .pipe( browserSync.stream() )
+);
+
+/**
+ * Minify compiled JavaScript.
+ *
+ * https://www.npmjs.com/package/gulp-uglify
+ */
+gulp.task( 'uglify', [ 'concat' ], () =>
+ gulp.src( paths.scripts )
+ .pipe( rename( {'suffix': '.min'} ) )
+ .pipe( plumber( {'errorHandler': handleErrors} ) )
+ .pipe( uglify( {
+ 'mangle': false
+ } ) )
+ .pipe( gulp.dest( 'assets/js' ) )
+);
+
+/**
+ * Delete the theme's .pot before we create a new one.
+ */
+gulp.task( 'clean:pot', () =>
+ del( [ 'languages/_s.pot' ] )
+);
+
+/**
+ * Scan the theme and create a POT file.
+ *
+ * https://www.npmjs.com/package/gulp-wp-pot
+ */
+gulp.task( 'wp-pot', [ 'clean:pot' ], () =>
+ gulp.src( paths.php )
+ .pipe( plumber( {'errorHandler': handleErrors} ) )
+ .pipe( sort() )
+ .pipe( wpPot( {
+ 'domain': '_s',
+ 'destFile': '_s.pot',
+ 'package': '_s',
+ 'bugReport': 'http://_s.com',
+ 'lastTranslator': 'John Doe ',
+ 'team': 'Team '
+ } ) )
+ .pipe( gulp.dest( 'languages/' ) )
+);
+
+/**
+ * Sass linting.
+ *
+ * https://www.npmjs.com/package/sass-lint
+ */
+gulp.task( 'sass:lint', () =>
+ gulp.src( [
+ 'assets/sass/**/*.scss',
+ '!assets/sass/base/_normalize.scss',
+ '!assets/sass/base/_sprites.scss',
+ '!node_modules/**'
+ ] )
+ .pipe( sassLint() )
+ .pipe( sassLint.format() )
+ .pipe( sassLint.failOnError() )
+);
+
+/**
+ * JavaScript linting.
+ *
+ * https://www.npmjs.com/package/gulp-eslint
+ */
+gulp.task( 'js:lint', () =>
+ gulp.src( [
+ 'assets/scripts/concat/*.js',
+ 'assets/scripts/*.js',
+ '!assets/scripts/project.js',
+ '!assets/scripts/*.min.js',
+ '!Gruntfile.js',
+ '!Gulpfile.js',
+ '!node_modules/**'
+ ] )
+ .pipe( eslint() )
+ .pipe( eslint.format() )
+ .pipe( eslint.failAfterError() )
+);
+
+/**
+ * Process tasks and reload browsers on file changes.
+ *
+ * https://www.npmjs.com/package/browser-sync
+ */
+gulp.task( 'watch', function () {
+
+ // Kick off BrowserSync.
+ browserSync( {
+ 'open': false, // Open project in a new tab?
+ 'injectChanges': true, // Auto inject changes instead of full reload.
+ 'proxy': 'testing.dev', // Use http://_s.com:3000 to use BrowserSync.
+ 'watchOptions': {
+ 'debounceDelay': 1000 // Wait 1 second before injecting.
+ }
+ } );
+
+ // Run tasks when files change.
+ gulp.watch( paths.icons, [ 'icons' ] );
+ gulp.watch( paths.sass, [ 'styles' ] );
+ gulp.watch( paths.scripts, [ 'scripts' ] );
+ gulp.watch( paths.concat_scripts, [ 'scripts' ] );
+ gulp.watch( paths.sprites, [ 'sprites' ] );
+ gulp.watch( paths.php, [ 'markup' ] );
+} );
+
+/**
+ * Create individual tasks.
+ */
+gulp.task( 'markup', browserSync.reload );
+gulp.task( 'i18n', [ 'wp-pot' ] );
+gulp.task( 'icons', [ 'svg' ] );
+gulp.task( 'scripts', [ 'uglify' ] );
+gulp.task( 'styles', [ 'cssnano' ] );
+gulp.task( 'sprites', [ 'spritesmith' ] );
+gulp.task( 'lint', [ 'sass:lint', 'js:lint' ] );
+gulp.task( 'default', [ 'sprites', 'i18n', 'icons', 'styles', 'scripts', 'imagemin'] );
\ No newline at end of file
diff --git a/readme.txt b/boilerplate/README.md
similarity index 67%
rename from readme.txt
rename to boilerplate/README.md
index 1548d18..252e1d0 100644
--- a/readme.txt
+++ b/boilerplate/README.md
@@ -1,16 +1,16 @@
-=== DoubleClick for WordPress ===
-Contributors: inn_nerds, willhaynes24
-Donate link: https://inn.org/donate
-Tags: ads, doubleclick, publishers, news
-Requires at least: 4.0.0
-Tested up to: 4.8
-Stable tag: 0.2.1
-License: GPLv2 or later
-License URI: http://www.gnu.org/licenses/gpl-2.0.html
+# DoubleClick for WordPress #
+**Contributors:** innlabs, willhaynes24
+**Donate link:** https://labs.inn.org
+**Tags:** ads, doubleclick, publishers, news
+**Requires at least:** 4.0
+**Tested up to:** 4.8
+**Stable tag:** 0.2.1
+**License:** GPLv2
+**License URI:** http://www.gnu.org/licenses/gpl-2.0.html
Serve DoubleClick ads natively in WordPress. Built to make serving and targeting responsive ads easy.
-== Description ==
+## Description ##
This WordPress plugin gives site administrators an easy way to serve DFP inventory on their WordPress site.
@@ -18,8 +18,7 @@ Implementing is simple. Configure your network code and input your identifiers.
For more advanced documentation for developers and advanced users see [the official plugin docs](https://github.com/INN/DoubleClick-for-WordPress/blob/master/docs/index.md).
-
-== Installation ==
+## Installation ##
1. Upload the plugin directory to your `/wp-content/plugins/` directory
2. Activate the plugin through the 'Plugins' menu in WordPress
@@ -28,11 +27,20 @@ For more advanced documentation for developers and advanced users see [the offic
For more advanced documentation for developers and advanced users see [the official plugin docs](https://github.com/INN/DoubleClick-for-WordPress/tree/master/docs/index.md).
+### Manual Installation ###
+
+1. Upload the entire `/doubleclick-for-wordpress` directory to the `/wp-content/plugins/` directory.
+2. Activate DoubleClick for WordPress through the 'Plugins' menu in WordPress.
+
+## Frequently Asked Questions ##
+
-== Changelog ==
+## Screenshots ##
-= 0.2.1 =
+## Changelog ##
+
+### 0.2.1 ###
- Widget now includes a default stylesheet:
- setting `.display-none` to `display: none;` to support `jQuery.dfp.js`' utility styles
- centering ad units within the ad widgets.
@@ -42,8 +50,13 @@ For more advanced documentation for developers and advanced users see [the offic
- Numerous small bugfixes
- Tested up to WordPress 4.6
-= 0.1 =
+### 0.1 ###
- Initial beta release.
- Add support for displaying different sizes of ad unit based on the size of the viewport
+
+## Upgrade Notice ##
+
+### 0.2.1 ###
+First Release
diff --git a/boilerplate/assets/README.md b/boilerplate/assets/README.md
new file mode 100644
index 0000000..164ee50
--- /dev/null
+++ b/boilerplate/assets/README.md
@@ -0,0 +1,6 @@
+# DoubleClick for WordPress Assets #
+https://labs.inn.org
+Copyright (c) 2017 innlabs, willhaynes24
+Licensed under the GPLv2 license.
+
+Assets such as styles, javascript, and images.
\ No newline at end of file
diff --git a/boilerplate/assets/css/sass/styles.scss b/boilerplate/assets/css/sass/styles.scss
new file mode 100644
index 0000000..a2ad07f
--- /dev/null
+++ b/boilerplate/assets/css/sass/styles.scss
@@ -0,0 +1,22 @@
+/**
+ * DoubleClick for WordPress
+ * https://labs.inn.org
+ *
+ * Copyright (c) 2017 innlabs, willhaynes24
+ * Licensed under the GPLv2+ license.
+ */
+ .display-none {
+ display: none;
+ }
+ .widget_doubleclick_widget {
+ text-align: center;
+ }
+ .dfw-unit.display-block:before {
+ speak: auto;
+ text-transform: uppercase;
+ content: "Advertisement";
+ display: block;
+ text-align: center;
+ font-size: 14px;
+ color: #aaa;
+ }
diff --git a/boilerplate/assets/js/jquery.dfp.js b/boilerplate/assets/js/jquery.dfp.js
new file mode 100644
index 0000000..be68354
--- /dev/null
+++ b/boilerplate/assets/js/jquery.dfp.js
@@ -0,0 +1,653 @@
+/*!
+ * jQuery DFP v2.4.2
+ * http://github.com/coop182/jquery.dfp.js
+ *
+ * Copyright 2016 Matt Cooper
+ * Released under the MIT license
+ */
+
+(function (window, undefined) {
+ "use strict";
+
+ /**
+ * Make plugin UMD compatible
+ * Uses CommonJS, AMD or browser globals to create plugin.
+ */
+ (function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node/CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals
+ factory(window.jQuery || window.Zepto);
+ }
+ }(function ($) {
+
+ var
+
+ // Save Scope
+ dfpScript = this || {};
+
+ var
+ // DFP account ID
+ dfpID = '',
+
+ // Init counters
+ count = 0,
+ uid = 0,
+ rendered = 0,
+
+ // Default DFP selector
+ dfpSelector = '.adunit',
+
+ adsCouldNeverBeInitilized = false,
+
+ // Keep track of if we've already tried to load gpt.js before
+ dfpIsLoaded = false,
+
+ // Store adunit on div as:
+ storeAs = 'googleAdUnit',
+
+ /**
+ * Init function sets required params and loads Google's DFP script
+ * @param String id The DFP account ID
+ * @param String selector The adunit selector
+ * @param Object options Custom options to apply
+ */
+ init = function (id, selector, options) {
+ var $adCollection;
+
+ // Reset counters on each call
+ count = 0;
+ rendered = 0;
+
+ dfpID = id;
+ $adCollection = $(selector);
+
+ /**
+ * @returns {boolean}
+ */
+ dfpScript.shouldCheckForAdBlockers = function(){
+ return options ? typeof options.afterAdBlocked === 'function' : false;
+ };
+
+ // explicitly wait for loader to be completed, otherwise the googletag might not be available
+ dfpLoader(options, $adCollection).then(function(){
+ options = setOptions(options);
+ dfpScript.dfpOptions = options;
+
+ $(function () {
+ createAds(options, $adCollection);
+ displayAds(options, $adCollection);
+ });
+ });
+
+ },
+
+ /**
+ * Set the options for DFP
+ * @param Object options Custom options to apply
+ * @return Object extended options
+ */
+ setOptions = function (options) {
+
+ // Set default options
+ var dfpOptions = {
+ setTargeting: {},
+ setCategoryExclusion: '',
+ setLocation: '',
+ enableSingleRequest: true,
+ collapseEmptyDivs: 'original',
+ refreshExisting: true,
+ disablePublisherConsole: false,
+ disableInitialLoad: false,
+ setCentering: false,
+ noFetch: false,
+ namespace: undefined,
+ sizeMapping: {}
+ };
+
+ if (typeof options.setUrlTargeting === 'undefined' || options.setUrlTargeting) {
+ // Get URL Targeting
+ var urlTargeting = getUrlTargeting(options.url);
+ $.extend(true, dfpOptions.setTargeting, {
+ UrlHost: urlTargeting.Host,
+ UrlPath: urlTargeting.Path,
+ UrlQuery: urlTargeting.Query
+ });
+ }
+
+ // Merge options objects
+ $.extend(true, dfpOptions, options);
+
+ // If a custom googletag is specified, use it.
+ if (dfpOptions.googletag) {
+ window.googletag.cmd.push(function () {
+ $.extend(true, window.googletag, dfpOptions.googletag);
+ });
+ }
+
+ return dfpOptions;
+ },
+
+ /**
+ * Find and create all Ads
+ * @param Object dfpOptions options related to ad instantiation
+ * @param jQuery $adCollection collection of ads
+ * @return Array an array of ad units that have been created.
+ */
+ createAds = function (dfpOptions, $adCollection) {
+ var googletag = window.googletag;
+ // Loops through on page Ad units and gets ads for them.
+ $adCollection.each(function () {
+ var $adUnit = $(this);
+
+ count++;
+
+ // adUnit name
+ var adUnitName = getName($adUnit, dfpOptions);
+
+ // adUnit id - this will use an existing id or an auto generated one.
+ var adUnitID = getID($adUnit, adUnitName);
+
+ // get dimensions of the adUnit
+ var dimensions = getDimensions($adUnit);
+
+ // set existing content
+ $adUnit.data('existingContent', $adUnit.html());
+
+ // wipe html clean ready for ad and set the default display class.
+ $adUnit.html('').addClass('display-none');
+
+ // Push commands to DFP to create ads
+ googletag.cmd.push(function () {
+
+ var googleAdUnit,
+ $adUnitData = $adUnit.data(storeAs);
+
+ if ($adUnitData) {
+
+ // Get existing ad unit
+ googleAdUnit = $adUnitData;
+
+ } else {
+
+ // Build slotName for loading
+ var slotName;
+ if (dfpID === '') {
+ slotName = adUnitName;
+ } else {
+ slotName = '/' + dfpID + '/' + adUnitName;
+ }
+
+ // Create the ad - out of page or normal
+ if ($adUnit.data('outofpage')) {
+ googleAdUnit = googletag.defineOutOfPageSlot(slotName, adUnitID);
+ } else {
+ googleAdUnit = googletag.defineSlot(slotName, dimensions, adUnitID);
+ if ($adUnit.data('companion')) {
+ googleAdUnit = googleAdUnit.addService(googletag.companionAds());
+ }
+ }
+
+ googleAdUnit = googleAdUnit.addService(googletag.pubads());
+
+ }
+
+ // Sets custom targeting for just THIS ad unit if it has been specified
+ var targeting = $adUnit.data('targeting');
+ if (targeting) {
+ $.each(targeting, function (k, v) {
+ googleAdUnit.setTargeting(k, v);
+ });
+ }
+
+ // Sets custom exclusions for just THIS ad unit if it has been specified
+ var exclusions = $adUnit.data('exclusions');
+ if (exclusions) {
+ var exclusionsGroup = exclusions.split(',');
+ var valueTrimmed;
+ $.each(exclusionsGroup, function (k, v) {
+ valueTrimmed = $.trim(v);
+ if (valueTrimmed.length > 0) {
+ googleAdUnit.setCategoryExclusion(valueTrimmed);
+ }
+ });
+ }
+
+ // Sets responsive size mapping for just THIS ad unit if it has been specified
+ var mapping = $adUnit.data('size-mapping');
+ if (mapping && dfpOptions.sizeMapping[mapping]) {
+ // Convert verbose to DFP format
+ var map = googletag.sizeMapping();
+ $.each(dfpOptions.sizeMapping[mapping], function (k, v) {
+ map.addSize(v.browser, v.ad_sizes);
+ });
+ googleAdUnit.defineSizeMapping(map.build());
+ }
+
+ // Store googleAdUnit reference
+ $adUnit.data(storeAs, googleAdUnit);
+
+ // Allow altering of the ad slot before ad load
+ if (typeof dfpOptions.beforeEachAdLoaded === 'function') {
+ dfpOptions.beforeEachAdLoaded.call(this, $adUnit);
+ }
+ });
+
+ });
+
+ // Push DFP config options
+ googletag.cmd.push(function () {
+
+ var pubadsService = googletag.pubads();
+
+ if (dfpOptions.enableSingleRequest) {
+ pubadsService.enableSingleRequest();
+ }
+
+ $.each(dfpOptions.setTargeting, function (k, v) {
+ pubadsService.setTargeting(k, v);
+ });
+
+ var setLocation = dfpOptions.setLocation;
+ if (typeof setLocation === 'object') {
+ if (typeof setLocation.latitude === 'number' && typeof setLocation.longitude === 'number' &&
+ typeof setLocation.precision === 'number') {
+ pubadsService.setLocation(setLocation.latitude, setLocation.longitude, setLocation.precision);
+ } else if (typeof setLocation.latitude === 'number' && typeof setLocation.longitude === 'number') {
+ pubadsService.setLocation(setLocation.latitude, setLocation.longitude);
+ }
+ }
+
+ if (dfpOptions.setCategoryExclusion.length > 0) {
+ var exclusionsGroup = dfpOptions.setCategoryExclusion.split(',');
+ var valueTrimmed;
+
+ $.each(exclusionsGroup, function (k, v) {
+ valueTrimmed = $.trim(v);
+ if (valueTrimmed.length > 0) {
+ pubadsService.setCategoryExclusion(valueTrimmed);
+ }
+ });
+ }
+
+ if (dfpOptions.collapseEmptyDivs) {
+ pubadsService.collapseEmptyDivs();
+ }
+
+ if (dfpOptions.disablePublisherConsole) {
+ pubadsService.disablePublisherConsole();
+ }
+
+ if (dfpOptions.companionAds) {
+ googletag.companionAds().setRefreshUnfilledSlots(true);
+
+ if (!dfpOptions.disableInitialLoad) {
+ pubadsService.enableVideoAds();
+ }
+ }
+
+ if (dfpOptions.disableInitialLoad) {
+ pubadsService.disableInitialLoad();
+ }
+
+ if (dfpOptions.noFetch) {
+ pubadsService.noFetch();
+ }
+
+ if (dfpOptions.setCentering) {
+ pubadsService.setCentering(true);
+ }
+
+ // Setup event listener to listen for renderEnded event and fire callbacks.
+ pubadsService.addEventListener('slotRenderEnded', function (event) {
+
+ rendered++;
+
+ var $adUnit = $('#' + event.slot.getSlotId().getDomId());
+
+ var display = event.isEmpty ? 'none' : 'block';
+
+ // if the div has been collapsed but there was existing content expand the
+ // div and reinsert the existing content.
+ var $existingContent = $adUnit.data('existingContent');
+ if (display === 'none' && $.trim($existingContent).length > 0 &&
+ dfpOptions.collapseEmptyDivs === 'original') {
+ $adUnit.show().html($existingContent);
+ display = 'block display-original';
+ }
+
+ $adUnit.removeClass('display-none').addClass('display-' + display);
+
+ // Excute afterEachAdLoaded callback if provided
+ if (typeof dfpOptions.afterEachAdLoaded === 'function') {
+ dfpOptions.afterEachAdLoaded.call(this, $adUnit, event);
+ }
+
+ // Excute afterAllAdsLoaded callback if provided
+ if (typeof dfpOptions.afterAllAdsLoaded === 'function' && rendered === count) {
+ dfpOptions.afterAllAdsLoaded.call(this, $adCollection);
+ }
+
+ });
+
+ // this will work with AdblockPlus
+ if(dfpScript.shouldCheckForAdBlockers() && !googletag._adBlocked_) {
+ setTimeout(function () {
+ var slots = pubadsService.getSlots ? pubadsService.getSlots() : [];
+ if (slots.length > 0) {
+ $.get(slots[0].getContentUrl()).always(function (r) {
+ if (r.status !== 200) {
+ $.each(slots, function () {
+ var $adUnit = $('#' + this.getSlotId().getDomId());
+ dfpOptions.afterAdBlocked.call(dfpScript, $adUnit, this);
+ });
+ }
+ });
+ }
+ }, 0);
+ }
+
+ googletag.enableServices();
+
+ });
+
+ },
+
+ /**
+ * Display all created Ads
+ * @param {Object} dfpOptions options related to ad instantiation
+ * @param {jQuery} $adCollection collection of ads
+ */
+ displayAds = function (dfpOptions, $adCollection) {
+
+ var googletag = window.googletag;
+ // Check if google adLoader can be loaded, this will work with AdBlock
+ if(dfpScript.shouldCheckForAdBlockers() && !googletag._adBlocked_) {
+ if (googletag.getVersion) {
+ var script = '//partner.googleadservices.com/gpt/pubads_impl_' +
+ googletag.getVersion() + '.js';
+ $.getScript(script).always(function (r) {
+ if (r && r.statusText === 'error') {
+ $.each($adCollection, function () {
+ dfpOptions.afterAdBlocked.call(dfpScript, $(this));
+ });
+ }
+ });
+ }
+
+ }
+
+ $adCollection.each(function () {
+
+ var $adUnit = $(this),
+ $adUnitData = $adUnit.data(storeAs);
+
+ if (googletag._adBlocked_) {
+ if(dfpScript.shouldCheckForAdBlockers()) {
+ dfpOptions.afterAdBlocked.call(dfpScript, $adUnit);
+ }
+ }
+ if (dfpOptions.refreshExisting && $adUnitData && $adUnit.hasClass('display-block')) {
+
+ googletag.cmd.push(function () { googletag.pubads().refresh([$adUnitData]); });
+
+ } else {
+ googletag.cmd.push(function () { googletag.display($adUnit.attr('id')); });
+ }
+
+ });
+
+ },
+
+ /**
+ * Create an array of paths so that we can target DFP ads to Page URI's
+ * @return Array an array of URL parts that can be targeted.
+ */
+ getUrlTargeting = function (url) {
+
+ // Get the url and parse it to its component parts using regex from RFC2396 Appendix-B (https://tools.ietf.org/html/rfc2396#appendix-B)
+ var urlMatches = (url || window.location.toString()).match(/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/);
+ var matchedAuthority = urlMatches[4] || '';
+ var matchedPath = (urlMatches[5] || '').replace(/(.)\/$/, '$1');
+ var matchedQuery = urlMatches[7] || '';
+
+ // Get the query params for targeting against
+ var params = matchedQuery.replace(/\=/ig, ':').split('&');
+
+ return {
+ Host: matchedAuthority,
+ Path: matchedPath,
+ Query: params
+ };
+
+ },
+
+ /**
+ * Get the id of the adUnit div or generate a unique one.
+ * @param Object $adUnit The adunit to work with
+ * @param String adUnitName The name of the adunit
+ * @return String The ID of the adunit or a unique autogenerated ID
+ */
+ getID = function ($adUnit, adUnitName) {
+
+ uid++;
+ return $adUnit.attr('id') || $adUnit.attr('id', adUnitName.replace(/[^A-z0-9]/g, '_') + '-auto-gen-id-' + uid).attr('id');
+
+ },
+
+ /**
+ * Get the name of the Ad unit, either use the div id or
+ * check for the optional attribute data-adunit
+ * @param Object $adUnit The adunit to work with
+ * @param Object dfpOptions options related to ad instantiation
+ * @return String The name of the adunit, will be the same as inside DFP
+ */
+ getName = function ($adUnit, dfpOptions) {
+
+ var adUnitName = $adUnit.data('adunit') || dfpOptions.namespace || $adUnit.attr('id') || '';
+ if (typeof dfpOptions.alterAdUnitName === 'function') {
+ adUnitName = dfpOptions.alterAdUnitName.call(this, adUnitName, $adUnit);
+ }
+ return adUnitName;
+
+ },
+
+ /**
+ * Get the dimensions of the ad unit using the container div dimensions or
+ * check for the optional attribute data-dimensions
+ * @param Object $adUnit The adunit to work with
+ * @return Array The dimensions of the adunit (width, height)
+ */
+ getDimensions = function ($adUnit) {
+
+ var dimensions = [],
+ dimensionsData = $adUnit.data('dimensions');
+
+ // Check if data-dimensions are specified. If they aren't, use the dimensions of the ad unit div.
+ if (dimensionsData) {
+
+ var dimensionGroups = dimensionsData.split(',');
+
+ $.each(dimensionGroups, function (k, v) {
+
+ var dimensionSet = v.split('x');
+ dimensions.push([parseInt(dimensionSet[0], 10), parseInt(dimensionSet[1], 10)]);
+
+ });
+
+ } else {
+
+ dimensions.push([$adUnit.width(), $adUnit.height()]);
+
+ }
+
+ return dimensions;
+
+ },
+
+ /**
+ * Call the google DFP script - there is a little bit of error detection in here to detect
+ * if the dfp script has failed to load either through an error or it being blocked by an ad
+ * blocker... if it does not load we execute a dummy script to replace the real DFP.
+ *
+ * @param {Object} options
+ * @param {Array} $adCollection
+ */
+ dfpLoader = function (options, $adCollection) {
+
+ function execBlockEvents() {
+ if(dfpScript.shouldCheckForAdBlockers()) {
+ $.each($adCollection, function () {
+ options.afterAdBlocked.call(dfpScript, $(this));
+ });
+ }
+ }
+
+ // make sure we don't load gpt.js multiple times
+ dfpIsLoaded = dfpIsLoaded || $('script[src*="googletagservices.com/tag/js/gpt.js"]').length;
+ if (dfpIsLoaded) {
+ if(adsCouldNeverBeInitilized) {
+ execBlockEvents();
+ }
+ return $.Deferred().resolve();
+ }
+
+ var loaded = $.Deferred();
+
+ window.googletag = window.googletag || {};
+ window.googletag.cmd = window.googletag.cmd || [];
+
+ var gads = document.createElement('script');
+ gads.async = true;
+ gads.type = 'text/javascript';
+
+ // Adblock blocks the load of Ad scripts... so we check for that
+ gads.onerror = function () {
+ dfpBlocked();
+ loaded.resolve();
+ adsCouldNeverBeInitilized = true;
+ execBlockEvents();
+ };
+
+ gads.onload = function() {
+ // this will work with ghostery:
+ if (!googletag._loadStarted_) {
+ googletag._adBlocked_ = true;
+ execBlockEvents();
+ }
+ loaded.resolve();
+ };
+
+ var useSSL = 'https:' === document.location.protocol;
+ gads.src = (useSSL ? 'https:' : 'http:') +
+ '//www.googletagservices.com/tag/js/gpt.js';
+ var node = document.getElementsByTagName('script')[0];
+ node.parentNode.insertBefore(gads, node);
+
+ // Adblock plus seems to hide blocked scripts... so we check for that
+ if (gads.style.display === 'none') {
+ dfpBlocked();
+ }
+
+ return loaded;
+
+ },
+
+ /**
+ * This function gets called if DFP has been blocked by an adblocker
+ * it implements a dummy version of the dfp object and allows the script to excute its callbacks
+ * regardless of whether DFP is actually loaded or not... it is basically only useful for situations
+ * where you are laying DFP over existing content and need to init things like slide shows after the loading
+ * is completed.
+ */
+ dfpBlocked = function () {
+ var googletag = window.googletag;
+ // Get the stored dfp commands
+ var commands = googletag.cmd;
+
+ var _defineSlot = function (name, dimensions, id, oop) {
+ googletag.ads.push(id);
+ googletag.ads[id] = {
+ renderEnded: function () { },
+ addService: function () { return this; }
+ };
+
+ return googletag.ads[id];
+ };
+
+ // overwrite the dfp object - replacing the command array with a function and defining missing functions
+ googletag = {
+ cmd: {
+ push: function (callback) {
+ callback.call(dfpScript);
+ }
+ },
+ ads: [],
+ pubads: function () { return this; },
+ noFetch: function () { return this; },
+ disableInitialLoad: function () { return this; },
+ disablePublisherConsole: function () { return this; },
+ enableSingleRequest: function () { return this; },
+ setTargeting: function () { return this; },
+ collapseEmptyDivs: function () { return this; },
+ enableServices: function () { return this; },
+ defineSlot: function (name, dimensions, id) {
+ return _defineSlot(name, dimensions, id, false);
+ },
+ defineOutOfPageSlot: function (name, id) {
+ return _defineSlot(name, [], id, true);
+ },
+ display: function (id) {
+ googletag.ads[id].renderEnded.call(dfpScript);
+ return this;
+ }
+
+ };
+
+ // Execute any stored commands
+ $.each(commands, function (k, v) {
+ googletag.cmd.push(v);
+ });
+
+
+ };
+
+
+ /**
+ * Add function to the jQuery / Zepto namespace
+ * @param String id (Optional) The DFP account ID
+ * @param Object options (Optional) Custom options to apply
+ */
+ $.dfp = $.fn.dfp = function (id, options) {
+
+ options = options || {};
+
+ if (id === undefined) {
+ id = dfpID;
+ }
+
+ if (typeof id === 'object') {
+ options = id;
+ id = options.dfpID || dfpID;
+ }
+
+ var selector = this;
+
+ if (typeof this === 'function') {
+ selector = dfpSelector;
+ }
+
+ init(id, selector, options);
+
+ return this;
+
+ };
+
+ }));
+
+})(window);
diff --git a/boilerplate/assets/js/jquery.dfp.min.js b/boilerplate/assets/js/jquery.dfp.min.js
new file mode 100644
index 0000000..1cea571
--- /dev/null
+++ b/boilerplate/assets/js/jquery.dfp.min.js
@@ -0,0 +1,8 @@
+/**
+ * jQuery DFP v2.4.2
+ * http://github.com/coop182/jquery.dfp.js
+ *
+ * Copyright 2016 Matt Cooper
+ * Released under the MIT license
+ */
+!function(a,b){"use strict";!function(b){"function"==typeof define&&define.amd?define(["jquery"],b):b("object"==typeof exports?require("jquery"):a.jQuery||a.Zepto)}(function(c){var d=this||{},e="",f=0,g=0,h=0,i=".adunit",j=!1,k=!1,l="googleAdUnit",m=function(a,b,g){var i;f=0,h=0,e=a,i=c(b),d.shouldCheckForAdBlockers=function(){return g?"function"==typeof g.afterAdBlocked:!1},u(g,i).then(function(){g=n(g),d.dfpOptions=g,c(function(){o(g,i),p(g,i)})})},n=function(d){var e={setTargeting:{},setCategoryExclusion:"",setLocation:"",enableSingleRequest:!0,collapseEmptyDivs:"original",refreshExisting:!0,disablePublisherConsole:!1,disableInitialLoad:!1,setCentering:!1,noFetch:!1,namespace:b,sizeMapping:{}};if("undefined"==typeof d.setUrlTargeting||d.setUrlTargeting){var f=q(d.url);c.extend(!0,e.setTargeting,{UrlHost:f.Host,UrlPath:f.Path,UrlQuery:f.Query})}return c.extend(!0,e,d),e.googletag&&a.googletag.cmd.push(function(){c.extend(!0,a.googletag,e.googletag)}),e},o=function(b,g){var i=a.googletag;g.each(function(){var a=c(this);f++;var d=s(a,b),g=r(a,d),h=t(a);a.data("existingContent",a.html()),a.html("").addClass("display-none"),i.cmd.push(function(){var f,j=a.data(l);if(j)f=j;else{var k;k=""===e?d:"/"+e+"/"+d,a.data("outofpage")?f=i.defineOutOfPageSlot(k,g):(f=i.defineSlot(k,h,g),a.data("companion")&&(f=f.addService(i.companionAds()))),f=f.addService(i.pubads())}var m=a.data("targeting");m&&c.each(m,function(a,b){f.setTargeting(a,b)});var n=a.data("exclusions");if(n){var o,p=n.split(",");c.each(p,function(a,b){o=c.trim(b),o.length>0&&f.setCategoryExclusion(o)})}var q=a.data("size-mapping");if(q&&b.sizeMapping[q]){var r=i.sizeMapping();c.each(b.sizeMapping[q],function(a,b){r.addSize(b.browser,b.ad_sizes)}),f.defineSizeMapping(r.build())}a.data(l,f),"function"==typeof b.beforeEachAdLoaded&&b.beforeEachAdLoaded.call(this,a)})}),i.cmd.push(function(){var a=i.pubads();b.enableSingleRequest&&a.enableSingleRequest(),c.each(b.setTargeting,function(b,c){a.setTargeting(b,c)});var e=b.setLocation;if("object"==typeof e&&("number"==typeof e.latitude&&"number"==typeof e.longitude&&"number"==typeof e.precision?a.setLocation(e.latitude,e.longitude,e.precision):"number"==typeof e.latitude&&"number"==typeof e.longitude&&a.setLocation(e.latitude,e.longitude)),b.setCategoryExclusion.length>0){var j,k=b.setCategoryExclusion.split(",");c.each(k,function(b,d){j=c.trim(d),j.length>0&&a.setCategoryExclusion(j)})}b.collapseEmptyDivs&&a.collapseEmptyDivs(),b.disablePublisherConsole&&a.disablePublisherConsole(),b.companionAds&&(i.companionAds().setRefreshUnfilledSlots(!0),b.disableInitialLoad||a.enableVideoAds()),b.disableInitialLoad&&a.disableInitialLoad(),b.noFetch&&a.noFetch(),b.setCentering&&a.setCentering(!0),a.addEventListener("slotRenderEnded",function(a){h++;var d=c("#"+a.slot.getSlotId().getDomId()),e=a.isEmpty?"none":"block",i=d.data("existingContent");"none"===e&&c.trim(i).length>0&&"original"===b.collapseEmptyDivs&&(d.show().html(i),e="block display-original"),d.removeClass("display-none").addClass("display-"+e),"function"==typeof b.afterEachAdLoaded&&b.afterEachAdLoaded.call(this,d,a),"function"==typeof b.afterAllAdsLoaded&&h===f&&b.afterAllAdsLoaded.call(this,g)}),d.shouldCheckForAdBlockers()&&!i._adBlocked_&&setTimeout(function(){var e=a.getSlots?a.getSlots():[];e.length>0&&c.get(e[0].getContentUrl()).always(function(a){200!==a.status&&c.each(e,function(){var a=c("#"+this.getSlotId().getDomId());b.afterAdBlocked.call(d,a,this)})})},0),i.enableServices()})},p=function(b,e){var f=a.googletag;if(d.shouldCheckForAdBlockers()&&!f._adBlocked_&&f.getVersion){var g="//partner.googleadservices.com/gpt/pubads_impl_"+f.getVersion()+".js";c.getScript(g).always(function(a){a&&"error"===a.statusText&&c.each(e,function(){b.afterAdBlocked.call(d,c(this))})})}e.each(function(){var a=c(this),e=a.data(l);f._adBlocked_&&d.shouldCheckForAdBlockers()&&b.afterAdBlocked.call(d,a),f.cmd.push(b.refreshExisting&&e&&a.hasClass("display-block")?function(){f.pubads().refresh([e])}:function(){f.display(a.attr("id"))})})},q=function(b){var c=(b||a.location.toString()).match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/),d=c[4]||"",e=(c[5]||"").replace(/(.)\/$/,"$1"),f=c[7]||"",g=f.replace(/\=/gi,":").split("&");return{Host:d,Path:e,Query:g}},r=function(a,b){return g++,a.attr("id")||a.attr("id",b.replace(/[^A-z0-9]/g,"_")+"-auto-gen-id-"+g).attr("id")},s=function(a,b){var c=a.data("adunit")||b.namespace||a.attr("id")||"";return"function"==typeof b.alterAdUnitName&&(c=b.alterAdUnitName.call(this,c,a)),c},t=function(a){var b=[],d=a.data("dimensions");if(d){var e=d.split(",");c.each(e,function(a,c){var d=c.split("x");b.push([parseInt(d[0],10),parseInt(d[1],10)])})}else b.push([a.width(),a.height()]);return b},u=function(b,e){function f(){d.shouldCheckForAdBlockers()&&c.each(e,function(){b.afterAdBlocked.call(d,c(this))})}if(k=k||c('script[src*="googletagservices.com/tag/js/gpt.js"]').length)return j&&f(),c.Deferred().resolve();var g=c.Deferred();a.googletag=a.googletag||{},a.googletag.cmd=a.googletag.cmd||[];var h=document.createElement("script");h.async=!0,h.type="text/javascript",h.onerror=function(){v(),g.resolve(),j=!0,f()},h.onload=function(){googletag._loadStarted_||(googletag._adBlocked_=!0,f()),g.resolve()};var i="https:"===document.location.protocol;h.src=(i?"https:":"http:")+"//www.googletagservices.com/tag/js/gpt.js";var l=document.getElementsByTagName("script")[0];return l.parentNode.insertBefore(h,l),"none"===h.style.display&&v(),g},v=function(){var b=a.googletag,e=b.cmd,f=function(a,c,d,e){return b.ads.push(d),b.ads[d]={renderEnded:function(){},addService:function(){return this}},b.ads[d]};b={cmd:{push:function(a){a.call(d)}},ads:[],pubads:function(){return this},noFetch:function(){return this},disableInitialLoad:function(){return this},disablePublisherConsole:function(){return this},enableSingleRequest:function(){return this},setTargeting:function(){return this},collapseEmptyDivs:function(){return this},enableServices:function(){return this},defineSlot:function(a,b,c){return f(a,b,c,!1)},defineOutOfPageSlot:function(a,b){return f(a,[],b,!0)},display:function(a){return b.ads[a].renderEnded.call(d),this}},c.each(e,function(a,c){b.cmd.push(c)})};c.dfp=c.fn.dfp=function(a,c){c=c||{},a===b&&(a=e),"object"==typeof a&&(c=a,a=c.dfpID||e);var d=this;return"function"==typeof this&&(d=i),m(a,d,c),this}})}(window);
\ No newline at end of file
diff --git a/boilerplate/assets/repo/README.md b/boilerplate/assets/repo/README.md
new file mode 100644
index 0000000..a7f6ccc
--- /dev/null
+++ b/boilerplate/assets/repo/README.md
@@ -0,0 +1,6 @@
+# DoubleClick for WordPress Repo Assets #
+https://labs.inn.org
+Copyright (c) 2017 innlabs, willhaynes24
+Licensed under the GPLv2 license.
+
+Assets such as screenshots and banner for WordPress.org plugin repository listing.
\ No newline at end of file
diff --git a/boilerplate/bin/install-wp-tests.sh b/boilerplate/bin/install-wp-tests.sh
new file mode 100644
index 0000000..fdf3542
--- /dev/null
+++ b/boilerplate/bin/install-wp-tests.sh
@@ -0,0 +1,113 @@
+#!/usr/bin/env bash
+
+if [ $# -lt 3 ]; then
+ echo "usage: $0 [db-host] [wp-version]"
+ exit 1
+fi
+
+DB_NAME=$1
+DB_USER=$2
+DB_PASS=$3
+DB_HOST=${4-localhost}
+WP_VERSION=${5-latest}
+
+WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
+WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
+
+download() {
+ if [ `which curl` ]; then
+ curl -s "$1" > "$2";
+ elif [ `which wget` ]; then
+ wget -nv -O "$2" "$1"
+ fi
+}
+
+if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
+ WP_TESTS_TAG="tags/$WP_VERSION"
+else
+ # http serves a single offer, whereas https serves multiple. we only want one
+ download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
+ grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
+ LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
+ if [[ -z "$LATEST_VERSION" ]]; then
+ echo "Latest WordPress version could not be found"
+ exit 1
+ fi
+ WP_TESTS_TAG="tags/$LATEST_VERSION"
+fi
+
+set -ex
+
+install_wp() {
+
+ if [ -d $WP_CORE_DIR ]; then
+ return;
+ fi
+
+ mkdir -p $WP_CORE_DIR
+
+ if [ $WP_VERSION == 'latest' ]; then
+ local ARCHIVE_NAME='latest'
+ else
+ local ARCHIVE_NAME="wordpress-$WP_VERSION"
+ fi
+
+ download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz
+ tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
+
+ download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
+}
+
+install_test_suite() {
+ # portable in-place argument for both GNU sed and Mac OSX sed
+ if [[ $(uname -s) == 'Darwin' ]]; then
+ local ioption='-i .bak'
+ else
+ local ioption='-i'
+ fi
+
+ # set up testing suite if it doesn't yet exist
+ if [ ! -d $WP_TESTS_DIR ]; then
+ # set up testing suite
+ mkdir -p $WP_TESTS_DIR
+ svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
+ fi
+
+ cd $WP_TESTS_DIR
+
+ if [ ! -f wp-tests-config.php ]; then
+ download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
+ sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php
+ sed $ioption "s:define( 'WP_DEBUG', true );:define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true );:" "$WP_TESTS_DIR"/wp-tests-config.php
+ sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
+ sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
+ sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
+ sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
+ fi
+
+}
+
+install_db() {
+ # parse DB_HOST for port or socket references
+ local PARTS=(${DB_HOST//\:/ })
+ local DB_HOSTNAME=${PARTS[0]};
+ local DB_SOCK_OR_PORT=${PARTS[1]};
+ local EXTRA=""
+
+ if ! [ -z $DB_HOSTNAME ] ; then
+ if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
+ EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
+ elif ! [ -z $DB_SOCK_OR_PORT ] ; then
+ EXTRA=" --socket=$DB_SOCK_OR_PORT"
+ elif ! [ -z $DB_HOSTNAME ] ; then
+ EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
+ fi
+ fi
+
+ # create database
+ mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
+}
+
+install_wp
+install_test_suite
+install_db
diff --git a/bower.json b/boilerplate/bower.json
similarity index 100%
rename from bower.json
rename to boilerplate/bower.json
diff --git a/docs/img/create-key.png b/boilerplate/docs/img/create-key.png
similarity index 100%
rename from docs/img/create-key.png
rename to boilerplate/docs/img/create-key.png
diff --git a/docs/img/custom-criteria.png b/boilerplate/docs/img/custom-criteria.png
similarity index 100%
rename from docs/img/custom-criteria.png
rename to boilerplate/docs/img/custom-criteria.png
diff --git a/docs/img/dfw.png b/boilerplate/docs/img/dfw.png
similarity index 100%
rename from docs/img/dfw.png
rename to boilerplate/docs/img/dfw.png
diff --git a/docs/img/key-values.png b/boilerplate/docs/img/key-values.png
similarity index 100%
rename from docs/img/key-values.png
rename to boilerplate/docs/img/key-values.png
diff --git a/docs/img/name-key.png b/boilerplate/docs/img/name-key.png
similarity index 100%
rename from docs/img/name-key.png
rename to boilerplate/docs/img/name-key.png
diff --git a/docs/img/network-code.png b/boilerplate/docs/img/network-code.png
similarity index 100%
rename from docs/img/network-code.png
rename to boilerplate/docs/img/network-code.png
diff --git a/docs/img/targeting.png b/boilerplate/docs/img/targeting.png
similarity index 100%
rename from docs/img/targeting.png
rename to boilerplate/docs/img/targeting.png
diff --git a/docs/img/widget.png b/boilerplate/docs/img/widget.png
similarity index 100%
rename from docs/img/widget.png
rename to boilerplate/docs/img/widget.png
diff --git a/boilerplate/doubleclick-for-wordpress.php b/boilerplate/doubleclick-for-wordpress.php
new file mode 100644
index 0000000..e358ae7
--- /dev/null
+++ b/boilerplate/doubleclick-for-wordpress.php
@@ -0,0 +1,373 @@
+basename = plugin_basename( __FILE__ );
+ $this->url = plugin_dir_url( __FILE__ );
+ $this->path = plugin_dir_path( __FILE__ );
+ }
+
+ /**
+ * Attach other plugin classes to the base plugin class.
+ *
+ * @since 0.2.1
+ */
+ public function plugin_classes() {
+ // $this->plugin_class = new DCFWP_Plugin_Class( $this );
+
+ } // END OF PLUGIN CLASSES FUNCTION
+
+ /**
+ * Add hooks and filters.
+ * Priority needs to be
+ * < 10 for CPT_Core,
+ * < 5 for Taxonomy_Core,
+ * and 0 for Widgets because widgets_init runs at init priority 1.
+ *
+ * @since 0.2.1
+ */
+ public function hooks() {
+ add_action( 'init', array( $this, 'init' ), 0 );
+ do_action( 'dfw_setup' );
+ }
+
+ /**
+ * Activate the plugin.
+ *
+ * @since 0.2.1
+ */
+ public function _activate() {
+ // Bail early if requirements aren't met.
+ if ( ! $this->check_requirements() ) {
+ return;
+ }
+
+ // Make sure any rewrite functionality has been loaded.
+ flush_rewrite_rules();
+ }
+
+ /**
+ * Deactivate the plugin.
+ * Uninstall routines should be in uninstall.php.
+ *
+ * @since 0.2.1
+ */
+ public function _deactivate() {
+ // Add deactivation cleanup functionality here.
+ }
+
+ /**
+ * Init hooks
+ *
+ * @since 0.2.1
+ */
+ public function init() {
+
+ // Bail early if requirements aren't met.
+ if ( ! $this->check_requirements() ) {
+ return;
+ }
+
+ // Load translated strings for plugin.
+ load_plugin_textdomain( 'doubleclick-for-wordpress', false, dirname( $this->basename ) . '/languages/' );
+
+ // Initialize plugin classes.
+ $this->plugin_classes();
+ }
+
+ /**
+ * Check if the plugin meets requirements and
+ * disable it if they are not present.
+ *
+ * @since 0.2.1
+ *
+ * @return boolean True if requirements met, false if not.
+ */
+ public function check_requirements() {
+
+ // Bail early if plugin meets requirements.
+ if ( $this->meets_requirements() ) {
+ return true;
+ }
+
+ // Add a dashboard notice.
+ add_action( 'all_admin_notices', array( $this, 'requirements_not_met_notice' ) );
+
+ // Deactivate our plugin.
+ add_action( 'admin_init', array( $this, 'deactivate_me' ) );
+
+ // Didn't meet the requirements.
+ return false;
+ }
+
+ /**
+ * Deactivates this plugin, hook this function on admin_init.
+ *
+ * @since 0.2.1
+ */
+ public function deactivate_me() {
+
+ // We do a check for deactivate_plugins before calling it, to protect
+ // any developers from accidentally calling it too early and breaking things.
+ if ( function_exists( 'deactivate_plugins' ) ) {
+ deactivate_plugins( $this->basename );
+ }
+ }
+
+ /**
+ * Check that all plugin requirements are met.
+ *
+ * @since 0.2.1
+ *
+ * @return boolean True if requirements are met.
+ */
+ public function meets_requirements() {
+
+ // Do checks for required classes / functions or similar.
+ // Add detailed messages to $this->activation_errors array.
+ return true;
+ }
+
+ /**
+ * Adds a notice to the dashboard if the plugin requirements are not met.
+ *
+ * @since 0.2.1
+ */
+ public function requirements_not_met_notice() {
+
+ // Compile default message.
+ $default_message = sprintf( __( 'DoubleClick for WordPress is missing requirements and has been deactivated. Please make sure all requirements are available.', 'doubleclick-for-wordpress' ), admin_url( 'plugins.php' ) );
+
+ // Default details to null.
+ $details = null;
+
+ // Add details if any exist.
+ if ( $this->activation_errors && is_array( $this->activation_errors ) ) {
+ $details = '' . implode( ' ', $this->activation_errors ) . '';
+ }
+
+ // Output errors.
+ ?>
+
+
+
+
+ $field;
+ default:
+ throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field );
+ }
+ }
+
+ /**
+ * Include a file from the includes directory.
+ *
+ * @since 0.2.1
+ *
+ * @param string $filename Name of the file to be included.
+ * @return boolean Result of include call.
+ */
+ public static function include_file( $filename ) {
+ $file = self::dir( $filename . '.php' );
+ if ( file_exists( $file ) ) {
+ return include_once( $file );
+ }
+ return false;
+ }
+
+ /**
+ * This plugin's directory.
+ *
+ * @since 0.2.1
+ *
+ * @param string $path (optional) appended path.
+ * @return string Directory and path.
+ */
+ public static function dir( $path = '' ) {
+ static $dir;
+ $dir = $dir ? $dir : trailingslashit( dirname( __FILE__ ) );
+ return $dir . $path;
+ }
+
+ /**
+ * This plugin's url.
+ *
+ * @since 0.2.1
+ *
+ * @param string $path (optional) appended path.
+ * @return string URL and path.
+ */
+ public static function url( $path = '' ) {
+ static $url;
+ $url = $url ? $url : trailingslashit( plugin_dir_url( __FILE__ ) );
+ return $url . $path;
+ }
+}
+
+/**
+ * Grab the DoubleClick_For_WordPress object and return it.
+ * Wrapper for DoubleClick_For_WordPress::get_instance().
+ *
+ * @since 0.2.1
+ * @return DoubleClick_For_WordPress Singleton instance of plugin class.
+ */
+function doubleclick_for_wordpress() {
+ return DoubleClick_For_WordPress::get_instance();
+}
+
+// Kick it off.
+add_action( 'plugins_loaded', array( doubleclick_for_wordpress(), 'hooks' ) );
+
+// Activation and deactivation.
+register_activation_hook( __FILE__, array( doubleclick_for_wordpress(), '_activate' ) );
+register_deactivation_hook( __FILE__, array( doubleclick_for_wordpress(), '_deactivate' ) );
diff --git a/boilerplate/includes/README.md b/boilerplate/includes/README.md
new file mode 100644
index 0000000..0d7a1a6
--- /dev/null
+++ b/boilerplate/includes/README.md
@@ -0,0 +1,6 @@
+# DoubleClick for WordPress Includes #
+https://labs.inn.org
+Copyright (c) 2017 innlabs, willhaynes24
+Licensed under the GPLv2 license.
+
+Additional PHP functionality goes here.
\ No newline at end of file
diff --git a/boilerplate/languages b/boilerplate/languages
new file mode 100644
index 0000000..462a40f
--- /dev/null
+++ b/boilerplate/languages
@@ -0,0 +1,21 @@
+# Copyright (C) 2017 _s
+# This file is distributed under the same license as the _s package.
+msgid ""
+msgstr ""
+"Project-Id-Version: _s\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language-Team: Team \n"
+"Last-Translator: John Doe \n"
+"Report-Msgid-Bugs-To: http://_s.com\n"
+"X-Poedit-Basepath: ..\n"
+"X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n"
+"X-Poedit-SearchPath-0: .\n"
+"X-Poedit-SearchPathExcluded-0: *.js\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: node_modules/grunt-wp-i18n/test/fixtures/basic-theme/page-templates/full-width.php:2
+msgid "Full Width"
+msgstr ""
diff --git a/boilerplate/package.json b/boilerplate/package.json
new file mode 100644
index 0000000..905d952
--- /dev/null
+++ b/boilerplate/package.json
@@ -0,0 +1,57 @@
+{
+ "name": "doubleclick-for-wordpress",
+ "title": "DoubleClick for WordPress",
+ "version": "0.2.1",
+ "description": "Serve DoubleClick ads natively in WordPress. Built to make serving and targeting responsive ads easy.",
+ "author": {
+ "name": "innlabs, willhaynes24",
+ "url": "https://labs.inn.org"
+ },
+ "license": "GPLv2",
+ "devDependencies": {
+ "grunt": "latest",
+ "grunt-contrib-watch": "latest",
+ "grunt-wp-i18n": "latest",
+ "grunt-contrib-copy": "latest",
+ "grunt-text-replace": "latest",
+ "grunt-contrib-clean": "latest",
+ "grunt-contrib-compress": "latest",
+ "grunt-wp-deploy": "latest",
+ "load-grunt-tasks": "latest",
+ "autoprefixer": "latest",
+ "babel-preset-es2015": "latest",
+ "bourbon": "latest",
+ "bourbon-neat": "latest",
+ "browser-sync": "latest",
+ "css-mqpacker": "latest",
+ "del": "latest",
+ "eslint-config-wordpress": "latest",
+ "glob": "latest",
+ "gulp": "latest",
+ "gulp-babel": "latest",
+ "gulp-cheerio": "latest",
+ "gulp-concat": "latest",
+ "gulp-cssnano": "latest",
+ "gulp-eslint": "latest",
+ "gulp-imagemin": "latest",
+ "gulp-notify": "latest",
+ "gulp-plumber": "latest",
+ "gulp-postcss": "latest",
+ "gulp-rename": "latest",
+ "gulp-sass": "latest",
+ "gulp-sass-lint": "latest",
+ "gulp-sort": "latest",
+ "gulp-sourcemaps": "latest",
+ "gulp-svgmin": "latest",
+ "gulp-svgstore": "latest",
+ "gulp-uglify": "latest",
+ "gulp-util": "latest",
+ "gulp-wp-pot": "latest",
+ "gulp.spritesmith": "latest"
+ },
+ "scripts": {
+ "test": "dockunit",
+ "preversion": "npm test",
+ "version": "grunt version && git add ."
+ }
+}
diff --git a/boilerplate/phpcs.xml b/boilerplate/phpcs.xml
new file mode 100644
index 0000000..405ccd7
--- /dev/null
+++ b/boilerplate/phpcs.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ A modified set of rules, based on the WordPress Coding Standards.
+
+
+
+
+
+
+
+
+
diff --git a/boilerplate/phpunit.xml b/boilerplate/phpunit.xml
new file mode 100644
index 0000000..44f0fdb
--- /dev/null
+++ b/boilerplate/phpunit.xml
@@ -0,0 +1,14 @@
+
+
+
+ ./tests/
+
+
+
diff --git a/release.sh b/boilerplate/release.sh
similarity index 100%
rename from release.sh
rename to boilerplate/release.sh
diff --git a/boilerplate/tests/bootstrap.php b/boilerplate/tests/bootstrap.php
new file mode 100644
index 0000000..f007ab6
--- /dev/null
+++ b/boilerplate/tests/bootstrap.php
@@ -0,0 +1,35 @@
+assertTrue( class_exists( 'DoubleClick_For_WordPress') );
+ }
+
+ /**
+ * Test that our main helper function is an instance of our class.
+ *
+ * @since 0.2.1
+ */
+ function test_get_instance() {
+ $this->assertInstanceOf( 'DoubleClick_For_WordPress', doubleclick_for_wordpress() );
+ }
+
+ /**
+ * Replace this with some actual testing code.
+ *
+ * @since 0.2.1
+ */
+ function test_sample() {
+ $this->assertTrue( true );
+ }
+}
diff --git a/css/dfp.css b/css/dfp.css
deleted file mode 100644
index 26f3fc4..0000000
--- a/css/dfp.css
+++ /dev/null
@@ -1,15 +0,0 @@
-.display-none {
- display: none;
-}
-.widget_doubleclick_widget {
- text-align: center;
-}
-.dfw-unit.display-block:before {
- speak: auto;
- text-transform: uppercase;
- content: "Advertisement";
- display: block;
- text-align: center;
- font-size: 14px;
- color: #aaa;
-}
diff --git a/docs/Colophon.md b/docs/Colophon.md
deleted file mode 100644
index 5904420..0000000
--- a/docs/Colophon.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Colophon
-
-#### Credits
-
-Built by [__Will Haynes__](https://github.com/willhaynes) ([@willhaynes](https://twitter.com/willhaynes)) for the [Institute for Nonprofit News](https://github.com/inn).
-
-#### License
-
-Released under [__GPLv2__](http://www.gnu.org/licenses/gpl-2.0.html).
\ No newline at end of file
diff --git a/docs/Developer-API.md b/docs/Developer-API.md
deleted file mode 100644
index c30bf21..0000000
--- a/docs/Developer-API.md
+++ /dev/null
@@ -1,105 +0,0 @@
-# Developer API
-
-A `global $DoubleClick` variable is defined on plugin init, making it possible to define breakpoints
-and place ads directly within your theme.
-
-__Quick Function Links:__
-
- * [$DoubleClick->register_breakpoint($identifer,$args)](#doubleclick-register_breakpointidentiferargs)
- * [$DoubleClick->place_ad($identifer,$size,$breakpoints)](#doubleclick-place_adidentifersizebreakpoints)
-
-* * *
-
-## 1. Define Breakpoints
-
-##### $DoubleClick->register_breakpoint($identifer,$args)
-
-You can make it easier for users to target breakpoints by defining them in `functions.php`
-
-##### Example:
-
-```php
-function ad_setup() {
-
- global $DoubleClick;
-
- // Optionally define the network code directly in functions.php.
- // $DoubleClick->networkCode = "xxxxxxx";
-
- /* Define Breakpoints */
- $DoubleClick->register_breakpoint('phone', array('minWidth'=> 0,'maxWidth'=>720));
- $DoubleClick->register_breakpoint('tablet', array('minWidth'=>760,'maxWidth'=>1040));
- $DoubleClick->register_breakpoint('desktop', array('minWidth'=>1040,'maxWidth'=>1220));
- $DoubleClick->register_breakpoint('xl', array('minWidth'=>1220,'maxWidth'=>9999));
-
-}
-add_action('dfw_setup','ad_setup');
-```
-
-##### Paramaters:
-
-__$identifer__
-
-`String` A unique identifier for this breakpoint
-
-__$args__
-
-`Array` An array of properties about the breakpoint. Currently the only keys supported are minWidth and maxWidth.
-
-* * *
-
-## 2. Place Ads
-
-### $DoubleClick->place_ad($identifer,$sizes,$args)
-
-Prints DOM to display an ad at the given breakpoint.
-
-##### Example:
-
-```php
-
-global $DoubleClick;
-
-// simple call:
-$DoubleClick->place_ad('my-identifer','300x250');
-
-// more options:
-$sizes = array(
- 'phone' => '300x50' // show a medium rectangle for phone and up.
- 'tablet' => '728x90' // show a leaderboard for tablet and up.
- 'desktop' => '' // show no ad for desktop and up.
- );
-$args = array(
- 'lazyLoad' => false // if set to true, the ad will load only once its within view on screen.
- );
-
-$DoubleClick->place_ad('my-identifier',$sizes,$args);
-```
-
-
-##### Paramaters:
-
-__$identifer__
-
-`String` The DFP identifier for an ad unit (DFP does not require you to create an identifier. If this does not match a value defined in DFP, a network-wide ad will still be requested).
-
-__$sizes__
-
-`Array|String` The size for the ad. Either a string for all breakpoints, or an array of sizes for each breakpoint.
-
-__$args__
-
-`Array` (optional) An array of additional arguments. Values:
-
- - __lazyLoad__: (true/false) setting this to true and the ad will be loaded only once it's within view on the page. Default is false.
-
-* * *
-
-## 3. Troubleshooting
-
-On any page with DoubleClick ads enabled (namely with DoubleClick js enqueued), load the included developer console to confirm data about advertisement delivery for each placement.
-
-#### Append the URL with the parameter:
-```
-?google_force_console
-```
diff --git a/docs/Targeting.md b/docs/Targeting.md
deleted file mode 100644
index 437202a..0000000
--- a/docs/Targeting.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# Targeting
-
-This plugin implements advanced DFP targeting criteria to allow trafficers to specify pages or groups of pages where line items should serve.
-
-* * *
-
-## 1. Example
-
-A local restaurant might wish to only have their ads shown a landing page and related article pages for a publisher's food category.
-
-
-
-_In the above example, this line item is targeting all posts in the Category "food"._
-
-* * *
-
-## 2. Available targeting criteria
-
-The following WordPress and general targeting criteria are defined for each ad call:
-
-#### WordPress Targeting —
-
-Targeting criteria specific to WordPress variables.
-
- - `Page` → Target the [type of page](http://codex.wordpress.org/Conditional_Tags).
-
- > Takes the values of 'home', 'front-page', 'admin', 'admin-bar-showing', 'single', 'archive', 'author', 'date' or 'search'.
-
- - `Category` → On single pages, target based on WordPress category. The value(s) passed are the WordPress slug for the category.
-
- >
-
- - `Tag` → On single pages, target based on WordPress tags. The value(s) passed are the WordPress slug for the tag.
-
-#### URL Targeting —
-
-Additional targeting criteria set by the URL of the page.
-
- - `inURL` → Target a piece of the page path.
-
- > __eg__. targeting the string '__/dvds__' would match [example.com**/dvds**/](http://example.com/dvds/), [example.com**/dvds**/page1](http://example.com/dvds/page1) and [example.com**/dvds**/page2](http://example.com/dvds/page2)
-
- - `URLIs` → Target the entire page path.
-
- > __eg__. targeting the string '__/books__' will **only** match [example.com**/books**](http://example.com/books/) and not [example.com**/books/page1**](http://example.com/books/page1). (Note: Any trailing '/' is removed.)
-
- - `Domain` → Target based on the domain.
-
- > eg. run different advertising on [staging.example.com](http://staging.example.com) and [example.com](http://example.com).
-
- - `Query` → Target a ?query var.
-
- > eg. target the url [example.com/?**movie=12**](http://example.com/news/) with the targeting string 'p:12'
-
-__Warning__: Targeting strings are limited to 40 characters long by DFP. Targeting URLIs or domains longer than that will result in error.
-
-* * *
-
-## 3. Defining targeting criteria in DFP
-
-DFP needs to be told what filter keys exist before they can be used.
-
-#### Example
-
-In Inventory > Custom Targeting, hit "New Key,"
-
-
-
-Enter a name for the key and "values type" to indicate whether this key is static or dynamic.
-
-For the purposes of this tutorial, we will use the `Category` targeting key. Also for our purposes, we will assume the site has a small number of predefined categories, such as "sports", "arts", "news" and "opinion". This is better suited for a value type of _"Users will select from predefined targeting values"_ (__static__).
-
-
-
-If a key is more __dynamic__, such as a blog that uses hundreds of categories, "values type" should be set it _"Users will enter targeting values when creating line items or checking inventory"_
-
-On the next screen enter values the key could take. This will be a list of categories, unique domains, url segments, tags, &c.
-
-
-
-#### Using the targeting criteria
-
-Now, when creating a line item, select "custom criteria" from the left hand menu under targeting. After entering a targeting key, select one or more options:
-
-
-
-This line item will show only on article pages that belong in the news category.
-
-The [available targeting criteria](#2-available-targeting-criteria) section above contains more information about what is possible with different criteria.
-
-
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index 12831d5..0000000
--- a/docs/index.md
+++ /dev/null
@@ -1,51 +0,0 @@
-#  DoubleClick for WordPress
-
-Serve DoubleClick ads natively in WordPress. Built to make serving responsive ads easy.
-
-Built by the [Institute for Nonprofit News](http://inn.org/), DoubleClick for WordPress works with [Project Largo](http://largoproject.org/) or any standalone WordPress blog.
-
-* * *
-
-## 1. What is this thing?
-
-This WordPress plugin serves inventory from a DoubleClick for Publisher account on a WordPress site.
-
-No need to copy and paste ad codes or header tags — the plugin generates all of this on its own.
-
-* * *
-
-## 2. How do I use it?
-
-For the most basic integration, only two steps are necessary.
-
-#### __2.1. Define Settings__ —
-
-Under _Settings > DoubleClick for WordPress_ update the field with your network code from DFP, and a place to define breakpoints to serve ads to.
-
-**NOTE:** Both Network Code and Breakpoints may be defined by a developer within the WordPress theme. If a developer already defined these values within the theme, a user will know based on their display in the plugin Settings page.
-
-
-
-#### __2.2 Placing Advertisements__ —
-
-Advertisements are placed in two ways.
-
-##### 1. Via Reusable Widget
-
-
-
- * The __identifier__ field is the name of a line item in DoubleClick for Publishers. If an line item with the same identifier in DoubleClick matches the identifier set in the widget, the ad will load (subject to conditional targeting set in DFP admin). If the identifier is blank or doesn't match a line item in DFP, the plugin attempts to load inventory from anywhere in the DFP account.
-
- * Based on breakpoints defined in plugin settings or theme, an __Inventory Size__ can be defined for each breakpoint set either in the plugin settings or via theme function.
- * For an ad the same __Inventory Size__ at every breakpoint, use that size in each breakpoint (i.e. `300x250`).
- * For an ad with multiple __Inventory Sizes__ (and corresponding creatives), define the appropriate Inventory Size for each breakpoint (i.e. `320x50` for a mobile breakpoint, `728x90` for tablet and desktop breakpoints).
-
-* * *
-
-##### 2. Via Theme Function
-
-See [Developer API](Developer-API.md) documentation.
-
-## 3. Is that it?
-
-Nope! Next [configure targeting](Targeting.md) and advanced users may look at the [developer api](developer-api/).
diff --git a/readme.md b/readme.md
deleted file mode 100644
index 44979cd..0000000
--- a/readme.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# DoubleClick for WordPress
-
-Serve DoubleClick ads natively in WordPress. Built to make serving responsive ads easy.
-
-[Read the documentation on GitHub](https://github.com/INN/DoubleClick-for-WordPress/tree/master/docs).
From 3b95655129cb955dc0053b291926816b79e00f7d Mon Sep 17 00:00:00 2001
From: rclations
Date: Thu, 22 Jun 2017 17:46:19 -0400
Subject: [PATCH 02/41] remove cmb2, rename options file/class
---
boilerplate/.bowerrc => .bowerrc | 0
boilerplate/.editorconfig => .editorconfig | 0
boilerplate/.eslintrc.js => .eslintrc.js | 0
boilerplate/.eslintrc.json => .eslintrc.json | 0
boilerplate/.gitignore => .gitignore | 0
boilerplate/.sass-lint.yml => .sass-lint.yml | 0
boilerplate/.travis.yml => .travis.yml | 0
boilerplate/.yo-rc.json => .yo-rc.json | 0
boilerplate/Dockunit.json => Dockunit.json | 0
boilerplate/Gulpfile.js => Gulpfile.js | 0
boilerplate/README.md => README.md | 0
{boilerplate/assets => assets}/README.md | 0
.../assets => assets}/css/sass/styles.scss | 0
.../assets => assets}/js/jquery.dfp.js | 0
.../assets => assets}/js/jquery.dfp.min.js | 0
{boilerplate/assets => assets}/repo/README.md | 0
{boilerplate/bin => bin}/install-wp-tests.sh | 0
boilerplate/bower.json => bower.json | 0
dfw.php | 12 -
{boilerplate/docs => docs}/img/create-key.png | Bin
.../docs => docs}/img/custom-criteria.png | Bin
{boilerplate/docs => docs}/img/dfw.png | Bin
{boilerplate/docs => docs}/img/key-values.png | Bin
{boilerplate/docs => docs}/img/name-key.png | Bin
.../docs => docs}/img/network-code.png | Bin
{boilerplate/docs => docs}/img/targeting.png | Bin
{boilerplate/docs => docs}/img/widget.png | Bin
...press.php => doubleclick-for-wordpress.php | 78 +--
{boilerplate/includes => includes}/README.md | 0
includes/class-options.php | 119 ++++
dfw-init.php => includes/dfw-init.php | 0
dfw-options.php => includes/dfw-options.php | 0
dfw-widget.php => includes/dfw-widget.php | 0
js/jquery.dfp.min.js | 8 -
js/jquery.dfw.js | 51 --
js/vendor/.keep | 0
js/vendor/jquery.dfp.js/.bower.json | 25 -
js/vendor/jquery.dfp.js/MIT-License.txt | 7 -
js/vendor/jquery.dfp.js/Readme.markdown | 360 ----------
js/vendor/jquery.dfp.js/bower.json | 15 -
js/vendor/jquery.dfp.js/dfp.jquery.json | 29 -
js/vendor/jquery.dfp.js/jquery.dfp.js | 646 ------------------
js/vendor/jquery.dfp.js/jquery.dfp.min.js | 8 -
js/vendor/jquery.dfp.js/package.json | 18 -
js/vendor/jquery.dfp.min.js | 8 -
boilerplate/languages => languages | 0
license.txt | 280 --------
mkdocs.yml | 2 -
boilerplate/package.json => package.json | 0
boilerplate/phpcs.xml => phpcs.xml | 0
boilerplate/phpunit.xml => phpunit.xml | 0
boilerplate/release.sh => release.sh | 0
{boilerplate/tests => tests}/bootstrap.php | 0
{boilerplate/tests => tests}/test-base.php | 0
tests/test-doubleclick.php | 36 +
55 files changed, 167 insertions(+), 1535 deletions(-)
rename boilerplate/.bowerrc => .bowerrc (100%)
rename boilerplate/.editorconfig => .editorconfig (100%)
rename boilerplate/.eslintrc.js => .eslintrc.js (100%)
rename boilerplate/.eslintrc.json => .eslintrc.json (100%)
rename boilerplate/.gitignore => .gitignore (100%)
rename boilerplate/.sass-lint.yml => .sass-lint.yml (100%)
rename boilerplate/.travis.yml => .travis.yml (100%)
rename boilerplate/.yo-rc.json => .yo-rc.json (100%)
rename boilerplate/Dockunit.json => Dockunit.json (100%)
rename boilerplate/Gulpfile.js => Gulpfile.js (100%)
rename boilerplate/README.md => README.md (100%)
rename {boilerplate/assets => assets}/README.md (100%)
rename {boilerplate/assets => assets}/css/sass/styles.scss (100%)
rename {boilerplate/assets => assets}/js/jquery.dfp.js (100%)
rename {boilerplate/assets => assets}/js/jquery.dfp.min.js (100%)
rename {boilerplate/assets => assets}/repo/README.md (100%)
rename {boilerplate/bin => bin}/install-wp-tests.sh (100%)
rename boilerplate/bower.json => bower.json (100%)
delete mode 100644 dfw.php
rename {boilerplate/docs => docs}/img/create-key.png (100%)
rename {boilerplate/docs => docs}/img/custom-criteria.png (100%)
rename {boilerplate/docs => docs}/img/dfw.png (100%)
rename {boilerplate/docs => docs}/img/key-values.png (100%)
rename {boilerplate/docs => docs}/img/name-key.png (100%)
rename {boilerplate/docs => docs}/img/network-code.png (100%)
rename {boilerplate/docs => docs}/img/targeting.png (100%)
rename {boilerplate/docs => docs}/img/widget.png (100%)
rename boilerplate/doubleclick-for-wordpress.php => doubleclick-for-wordpress.php (81%)
rename {boilerplate/includes => includes}/README.md (100%)
create mode 100644 includes/class-options.php
rename dfw-init.php => includes/dfw-init.php (100%)
rename dfw-options.php => includes/dfw-options.php (100%)
rename dfw-widget.php => includes/dfw-widget.php (100%)
delete mode 100644 js/jquery.dfp.min.js
delete mode 100644 js/jquery.dfw.js
delete mode 100644 js/vendor/.keep
delete mode 100644 js/vendor/jquery.dfp.js/.bower.json
delete mode 100644 js/vendor/jquery.dfp.js/MIT-License.txt
delete mode 100644 js/vendor/jquery.dfp.js/Readme.markdown
delete mode 100644 js/vendor/jquery.dfp.js/bower.json
delete mode 100644 js/vendor/jquery.dfp.js/dfp.jquery.json
delete mode 100644 js/vendor/jquery.dfp.js/jquery.dfp.js
delete mode 100644 js/vendor/jquery.dfp.js/jquery.dfp.min.js
delete mode 100644 js/vendor/jquery.dfp.js/package.json
delete mode 100644 js/vendor/jquery.dfp.min.js
rename boilerplate/languages => languages (100%)
delete mode 100644 license.txt
delete mode 100644 mkdocs.yml
rename boilerplate/package.json => package.json (100%)
rename boilerplate/phpcs.xml => phpcs.xml (100%)
rename boilerplate/phpunit.xml => phpunit.xml (100%)
rename boilerplate/release.sh => release.sh (100%)
rename {boilerplate/tests => tests}/bootstrap.php (100%)
rename {boilerplate/tests => tests}/test-base.php (100%)
create mode 100644 tests/test-doubleclick.php
diff --git a/boilerplate/.bowerrc b/.bowerrc
similarity index 100%
rename from boilerplate/.bowerrc
rename to .bowerrc
diff --git a/boilerplate/.editorconfig b/.editorconfig
similarity index 100%
rename from boilerplate/.editorconfig
rename to .editorconfig
diff --git a/boilerplate/.eslintrc.js b/.eslintrc.js
similarity index 100%
rename from boilerplate/.eslintrc.js
rename to .eslintrc.js
diff --git a/boilerplate/.eslintrc.json b/.eslintrc.json
similarity index 100%
rename from boilerplate/.eslintrc.json
rename to .eslintrc.json
diff --git a/boilerplate/.gitignore b/.gitignore
similarity index 100%
rename from boilerplate/.gitignore
rename to .gitignore
diff --git a/boilerplate/.sass-lint.yml b/.sass-lint.yml
similarity index 100%
rename from boilerplate/.sass-lint.yml
rename to .sass-lint.yml
diff --git a/boilerplate/.travis.yml b/.travis.yml
similarity index 100%
rename from boilerplate/.travis.yml
rename to .travis.yml
diff --git a/boilerplate/.yo-rc.json b/.yo-rc.json
similarity index 100%
rename from boilerplate/.yo-rc.json
rename to .yo-rc.json
diff --git a/boilerplate/Dockunit.json b/Dockunit.json
similarity index 100%
rename from boilerplate/Dockunit.json
rename to Dockunit.json
diff --git a/boilerplate/Gulpfile.js b/Gulpfile.js
similarity index 100%
rename from boilerplate/Gulpfile.js
rename to Gulpfile.js
diff --git a/boilerplate/README.md b/README.md
similarity index 100%
rename from boilerplate/README.md
rename to README.md
diff --git a/boilerplate/assets/README.md b/assets/README.md
similarity index 100%
rename from boilerplate/assets/README.md
rename to assets/README.md
diff --git a/boilerplate/assets/css/sass/styles.scss b/assets/css/sass/styles.scss
similarity index 100%
rename from boilerplate/assets/css/sass/styles.scss
rename to assets/css/sass/styles.scss
diff --git a/boilerplate/assets/js/jquery.dfp.js b/assets/js/jquery.dfp.js
similarity index 100%
rename from boilerplate/assets/js/jquery.dfp.js
rename to assets/js/jquery.dfp.js
diff --git a/boilerplate/assets/js/jquery.dfp.min.js b/assets/js/jquery.dfp.min.js
similarity index 100%
rename from boilerplate/assets/js/jquery.dfp.min.js
rename to assets/js/jquery.dfp.min.js
diff --git a/boilerplate/assets/repo/README.md b/assets/repo/README.md
similarity index 100%
rename from boilerplate/assets/repo/README.md
rename to assets/repo/README.md
diff --git a/boilerplate/bin/install-wp-tests.sh b/bin/install-wp-tests.sh
similarity index 100%
rename from boilerplate/bin/install-wp-tests.sh
rename to bin/install-wp-tests.sh
diff --git a/boilerplate/bower.json b/bower.json
similarity index 100%
rename from boilerplate/bower.json
rename to bower.json
diff --git a/dfw.php b/dfw.php
deleted file mode 100644
index cf86c10..0000000
--- a/dfw.php
+++ /dev/null
@@ -1,12 +0,0 @@
-plugin_class = new DCFWP_Plugin_Class( $this );
+ $this->options = new DCWP_Options( $this );
} // END OF PLUGIN CLASSES FUNCTION
/**
@@ -303,55 +292,12 @@ public function __get( $field ) {
case 'basename':
case 'url':
case 'path':
+ case 'doubleclick':
return $this->$field;
default:
throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field );
}
}
-
- /**
- * Include a file from the includes directory.
- *
- * @since 0.2.1
- *
- * @param string $filename Name of the file to be included.
- * @return boolean Result of include call.
- */
- public static function include_file( $filename ) {
- $file = self::dir( $filename . '.php' );
- if ( file_exists( $file ) ) {
- return include_once( $file );
- }
- return false;
- }
-
- /**
- * This plugin's directory.
- *
- * @since 0.2.1
- *
- * @param string $path (optional) appended path.
- * @return string Directory and path.
- */
- public static function dir( $path = '' ) {
- static $dir;
- $dir = $dir ? $dir : trailingslashit( dirname( __FILE__ ) );
- return $dir . $path;
- }
-
- /**
- * This plugin's url.
- *
- * @since 0.2.1
- *
- * @param string $path (optional) appended path.
- * @return string URL and path.
- */
- public static function url( $path = '' ) {
- static $url;
- $url = $url ? $url : trailingslashit( plugin_dir_url( __FILE__ ) );
- return $url . $path;
- }
}
/**
diff --git a/boilerplate/includes/README.md b/includes/README.md
similarity index 100%
rename from boilerplate/includes/README.md
rename to includes/README.md
diff --git a/includes/class-options.php b/includes/class-options.php
new file mode 100644
index 0000000..f1853c0
--- /dev/null
+++ b/includes/class-options.php
@@ -0,0 +1,119 @@
+plugin = $plugin;
+ $this->hooks();
+
+ // Set our title.
+ $this->title = esc_attr__( 'DoubleClick for WordPress Doubleclick', 'doubleclick-for-wordpress' );
+ }
+
+ /**
+ * Initiate our hooks.
+ *
+ * @since 0.2.1
+ */
+ public function hooks() {
+
+ // Hook in our actions to the admin.
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
+ add_action( 'admin_menu', array( $this, 'add_options_page' ) );
+
+ }
+
+ /**
+ * Register our setting to WP.
+ *
+ * @since 0.2.1
+ */
+ public function admin_init() {
+ register_setting( $this->key, $this->key );
+ }
+
+ /**
+ * Add menu options page.
+ *
+ * @since 0.2.1
+ */
+ public function add_options_page() {
+ $this->options_page = add_menu_page(
+ $this->title,
+ $this->title,
+ 'manage_options',
+ $this->key,
+ array( $this, 'admin_page_display' )
+ );
+
+ }
+
+ /**
+ * Admin page markup. Mostly handled by CMB2.
+ *
+ * @since 0.2.1
+ */
+ public function admin_page_display() {
+ ?>
+
+
+
+ 0&&g.setCategoryExclusion(n)})}var p=c.data("size-mapping");if(p&&k.sizeMapping[p]){var q=b.googletag.sizeMapping();a.each(k.sizeMapping[p],function(a,b){q.addSize(b.browser,b.ad_sizes)}),g.defineSizeMapping(q.build())}c.data(m,g),"function"==typeof k.beforeEachAdLoaded&&k.beforeEachAdLoaded.call(this,c)})}),b.googletag.cmd.push(function(){if(k.enableSingleRequest&&b.googletag.pubads().enableSingleRequest(),a.each(k.setTargeting,function(a,c){b.googletag.pubads().setTargeting(a,c)}),"object"==typeof k.setLocation&&("number"==typeof k.setLocation.latitude&&"number"==typeof k.setLocation.longitude&&"number"==typeof k.setLocation.precision?b.googletag.pubads().setLocation(k.setLocation.latitude,k.setLocation.longitude,k.setLocation.precision):"number"==typeof k.setLocation.latitude&&"number"==typeof k.setLocation.longitude&&b.googletag.pubads().setLocation(k.setLocation.latitude,k.setLocation.longitude)),k.setCategoryExclusion.length>0){var c,e=k.setCategoryExclusion.split(",");a.each(e,function(d,e){c=a.trim(e),c.length>0&&b.googletag.pubads().setCategoryExclusion(c)})}k.collapseEmptyDivs&&b.googletag.pubads().collapseEmptyDivs(),k.disablePublisherConsole&&b.googletag.pubads().disablePublisherConsole(),k.companionAds&&(b.googletag.companionAds().setRefreshUnfilledSlots(!0),k.disableInitialLoad||b.googletag.pubads().enableVideoAds()),k.disableInitialLoad&&b.googletag.pubads().disableInitialLoad(),k.noFetch&&b.googletag.pubads().noFetch(),b.googletag.pubads().addEventListener("slotRenderEnded",function(b){i++;var c=a("#"+b.slot.getSlotId().getDomId()),e=b.isEmpty?"none":"block",f=c.data("existingContent");"none"===e&&a.trim(f).length>0&&"original"===k.collapseEmptyDivs&&(c.show().html(f),e="block display-original"),c.removeClass("display-none").addClass("display-"+e),"function"==typeof k.afterEachAdLoaded&&k.afterEachAdLoaded.call(this,c,b),"function"==typeof k.afterAllAdsLoaded&&i===g&&k.afterAllAdsLoaded.call(this,d)}),b.googletag.enableServices()})},q=function(){d.each(function(){var c=a(this),d=c.data(m);b.googletag.cmd.push(k.refreshExisting&&d&&c.hasClass("display-block")?function(){b.googletag.pubads().refresh([d])}:function(){b.googletag.display(c.attr("id"))})})},r=function(){var a=b.location.pathname.replace(/\/$/,""),c=new RegExp("/([^/]*)","ig"),d=a.match(c),e=["/"],f="";if(d&&"/"!==a){var g="",h=d.length;if(h>0)for(var i=0;h>i;i++){g=d[i],e.push(g);for(var j=i+1;h>j;j++)g+=d[j],e.push(g);0===i&&(e.splice(-1,1),f=g)}e.push(f)}e=e.reverse();var k=(b.location.toString().replace(/\=/gi,":").match(/\?(.+)$/),RegExp.$1.split("&"));return{inURL:e,URLIs:e[0],Query:k}},s=function(a,b){return h++,a.attr("id")||a.attr("id",b.replace(/[^A-z0-9]/g,"_")+"-auto-gen-id-"+h).attr("id")},t=function(a){var b=a.data("adunit")||k.namespace||a.attr("id")||"";return"function"==typeof k.alterAdUnitName&&(b=k.alterAdUnitName.call(this,b,a)),b},u=function(b){var c=[],d=b.data("dimensions");if(d){var e=d.split(",");a.each(e,function(a,b){var d=b.split("x");c.push([parseInt(d[0],10),parseInt(d[1],10)])})}else c.push([b.width(),b.height()]);return c},v=function(){if(l=l||a('script[src*="googletagservices.com/tag/js/gpt.js"]').length,!l){b.googletag=b.googletag||{},b.googletag.cmd=b.googletag.cmd||[];var c=document.createElement("script");c.async=!0,c.type="text/javascript",c.onerror=function(){w()};var d="https:"===document.location.protocol;c.src=(d?"https:":"http:")+"//www.googletagservices.com/tag/js/gpt.js";var e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(c,e),"none"===c.style.display&&w()}},w=function(){var c=b.googletag.cmd;setTimeout(function(){var d=function(a,c,d){return b.googletag.ads.push(d),b.googletag.ads[d]={renderEnded:function(){},addService:function(){return this}},b.googletag.ads[d]};b.googletag={cmd:{push:function(a){a.call(e)}},ads:[],pubads:function(){return this},noFetch:function(){return this},disableInitialLoad:function(){return this},disablePublisherConsole:function(){return this},enableSingleRequest:function(){return this},setTargeting:function(){return this},collapseEmptyDivs:function(){return this},enableServices:function(){return this},defineSlot:function(a,b,c){return d(a,b,c,!1)},defineOutOfPageSlot:function(a,b){return d(a,[],b,!0)},display:function(a){return b.googletag.ads[a].renderEnded.call(e),this}},a.each(c,function(a,c){b.googletag.cmd.push(c)})},50)};a.dfp=a.fn.dfp=function(a,b){b=b||{},a===c&&(a=f),"object"==typeof a&&(b=a,a=b.dfpID||f);var d=this;return"function"==typeof this&&(d=j),n(a,d,b),this}}(window.jQuery||window.Zepto||window.tire,window);
\ No newline at end of file
diff --git a/js/jquery.dfw.js b/js/jquery.dfw.js
deleted file mode 100644
index 523bd50..0000000
--- a/js/jquery.dfw.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * A few lines of javascript to help the DoubleClick for WordPress plugin.
- * Extends jquery.dfw.min.js with some event listeners specific to us.
- */
-(function() {
- var $ = jQuery;
-
- // On window scroll check if there are any new ads to load.
- var lazyLoad = function() {
- // all the lazy load ads on the page.
- var lazyLoaders = $( '.dfw-lazy-load:not(.dfw-loaded)' ),
- // jQuery object to hold ads that actually need loading.
- toLoad = $( [] ),
- // window scrolltop.
- st = $( document ).scrollTop(),
- // window height.
- wh = $( window ).height();
-
- // determind with lazyLoaders needs toLoad.
- lazyLoaders.each(function () {
- var top = $( this ).offset().top;
-
- // how much futher down the page to load
- // the ad (so it's at least loading before it's on screen).
- var buffer = 200;
- if (top < st + wh + buffer) {
- toLoad = toLoad.add( $( this ) );
- }
- });
-
- // if we have some ads, then load 'em!
- if (toLoad.length > 0) {
- $( toLoad ).dfp({
- "dfpID": dfw.networkCode,
- "collapseEmptyDivs": false,
- "sizeMapping": dfw.mappings,
- "setTargeting": dfw.targeting
- }).addClass( 'dfw-loaded' );
- }
- };
-
- $( document ).ready(function(){
- // Watch for scroll events, and determine whether any ads
- // need lazy loading. Wait a few seconds for images and text to render
- // and units to reach their "true" depth on the page.
- $( window ).on( 'scroll', lazyLoad );
-
- // Run lazyLoad once on DOM ready to load any ads in view
- lazyLoad();
- });
-})();
diff --git a/js/vendor/.keep b/js/vendor/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/js/vendor/jquery.dfp.js/.bower.json b/js/vendor/jquery.dfp.js/.bower.json
deleted file mode 100644
index 4bde70c..0000000
--- a/js/vendor/jquery.dfp.js/.bower.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "name": "jquery.dfp",
- "version": "2.4.1",
- "main": "jquery.dfp.js",
- "ignore": [
- "img/",
- "tests/",
- ".gitattributes",
- ".gitignore",
- ".travis.yml",
- ".vimrc",
- "Gruntfile.js",
- "example-bootstrap.js"
- ],
- "homepage": "https://github.com/coop182/jquery.dfp.js",
- "_release": "2.4.1",
- "_resolution": {
- "type": "version",
- "tag": "2.4.1",
- "commit": "75d2b1cc513f5a04d93637ca61cf4b3ed605acc1"
- },
- "_source": "git://github.com/coop182/jquery.dfp.js.git",
- "_target": "~2.4.1",
- "_originalSource": "jquery.dfp.js"
-}
\ No newline at end of file
diff --git a/js/vendor/jquery.dfp.js/MIT-License.txt b/js/vendor/jquery.dfp.js/MIT-License.txt
deleted file mode 100644
index 4282de9..0000000
--- a/js/vendor/jquery.dfp.js/MIT-License.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Copyright (c) 2015 Matt Cooper
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/js/vendor/jquery.dfp.js/Readme.markdown b/js/vendor/jquery.dfp.js/Readme.markdown
deleted file mode 100644
index af53a4b..0000000
--- a/js/vendor/jquery.dfp.js/Readme.markdown
+++ /dev/null
@@ -1,360 +0,0 @@
-jQuery DFP - A jQuery implementation for Google DFP
-======================================================
-
-[](https://travis-ci.org/coop182/jquery.dfp.js)
-
-This script is a drop in solution for getting Double Click for Publishers (DFP) by Google working on your page. By including this script on your page and then initialising it in the ways described below you should find it very easy to get DFP working.
-
-Do not include any of the generated DFP script tags from the DFP admin on your page, this script replaces them.
-
-This script also works with [Zepto.js](http://zeptojs.com/)
-
-Demo / Ad unit tester
----------------------
-
-You can use [this page](http://coop182.github.io/jquery.dfp.js/dfptests/test.html?google_console=1&networkID=15572793&adunitID=Leader&dimensions=728x90) to test your DFP ads using the jquery.dfp.js script. There is some debug code included to help debug the ad delivery.
-
-You can also use the [Google Console](https://support.google.com/dfp_sb/answer/181070?hl=en-GB) to debug your ad units. This is done by by adding a "google_console=1" or "google_debug=1" to the url, and toggling the console by pressing CTRL + F10. Subsequent pagerequests will not require the parameters, and the console can be toggled. Adding the querystring "googfc" to an url, will also load the console, but also show it, without having to press CTRL + F10.
-
-Setup
------
-
-You can add ad units to your page in any location that you would like to display an ad.
-
-By default this script will look for ad units with a class of `adunit` but you can of course use jQuery selectors as well.
-
-The minimum information required for an ad unit to function is having the ad unit specified. To do this you can use the id parameter of the element, for example:
-
-```html
-
-```
-
-In the example above the ID of the div element will be used to look up a corresponding ad unit in DFP and the dimensions of the adunit will be set to the same dimensions of the div which could be defined in your CSS.
-
-You can optionally specify the adunit name and dimensions in the following way:
-
-```html
-
-```
-
-This method can be useful for including multiple copies of an ad unit with the same name which when part of a DFP placement will then pull in as many different creatives as possible.
-
-You can also specify multiple dimensions sets:
-
-```html
-
-```
-
-Also you can optionally specify custom targeting on a per ad unit basis in the following way:
-
-```html
-
-```
-
-Also you can optionally specify custom exclusion category on a per ad unit basis in the following way:
-
-```html
-
-```
-
-To create an out of page ad unit set the data-outofpage property on the ad unit. Dimensions are not required for out of page ad units.
-
-```html
-
-```
-
-In order to identify an ad unit on the page that is a video companion ad, set the data-companion attribute on that unit.
-
-```html
-
-```
-
-Usage
------
-
-Calling the script:
-
-```html
-
-
- DFP TEST
-
-
-
-
-
-
-
-
-
-
-
-```
-
-Using a bootstrap file (take a look at [example-bootstrap.js](https://github.com/coop182/jquery.dfp.js/blob/master/example-bootstrap.js)):
-
-```html
-
-
- DFP TEST
-
-
-
-
-
-
-
-
-
-```
-
-You can init the script in the following ways:
-
-```javascript
-$.dfp('xxxxxxxxx');
-```
-```javascript
-$.dfp({
- dfpID:'xxxxxxxxx'
-});
-```
-```javascript
-$('selector').dfp({
- dfpID:'xxxxxxxxx'
-});
-```
-```javascript
-$('selector').dfp({
- dfpID:'xxxxxxxxx',
- setCategoryExclusion: 'firstcategory, secondcategory'
-});
-```
-```javascript
-$('selector').dfp({
- dfpID:'xxxxxxxxx',
- setLocation: { latitude: 34, longitude: -45.12, precision: 1000 }
-});
-```
-
-```javascript
-$('selector').dfp({
- dfpID:'xxxxxxxxx',
- sizeMapping: {
- 'my-default': [
- {browser: [1024, 768], ad_sizes: [980, 185]},
- {browser: [ 980, 600], ad_sizes: [[728, 90], [640, 480]]}
- {browser: [ 0, 0], ad_sizes: [88, 31]}
- ],
- }
-});
-```
-
-Available Options
------------------
-
-
-
-
Option
-
Description
-
-
-
dfpID
-
This string is your unique DFP account ID.
-
-
-
setTargeting
-
This object is where you set custom targeting key value pairs. Also see the Default Targeting options that are set further down the page.
-
-
-
url
-
This string is the url used by the URL Targeting feature. The default value of this option is the value found by calling window.location.
-
-
-
setUrlTargeting
-
This boolean specifies whether the targeting should include information found in the url of the current page. The default value of this option is true.
-
-
-
setCategoryExclusion
-
This comma separated list sets category exclusions globally (page level).
-
-
-
setLocation
-
This object sets geolocalization. String values are not valid.
-
-
-
-
enableSingleRequest
-
This boolean sets whether the page ads are fetched with a single request or not, you will need to set this to false it you want to call $.dfp() more than once, typically you would do this if you are loading ad units into the page after the initial load.
-
-
-
collapseEmptyDivs
-
This can be set to true, false or 'original'. If its set to true the divs will be set to display:none if no line item is found. False means that the ad unit div will stay visible no matter what. Setting this to 'original' (the default option) means that the ad unit div will be hidden if no line items are found UNLESS there is some existing content inside the ad unit div tags. This allows you to have fall back content in the ad unit in the event that no ads are found.
-
-
-
refreshExisting
-
This boolean controls what happens when dfp is called multiple times on ad units. By default it is set to true which means that if an already initialised ad is initialised again it will instead be refreshed.
-
-
-
sizeMapping
-
Defines named size maps that can be used with in combination with the data-size-mapping attribute to enable responsive ad sizing (https://support.google.com/dfp_premium/answer/3423562?hl=en).
-
-
-
companionAds
-
If adding companion ads to accompany videos using the IMA SDK to serve video ads, then pass this parameter as true to identify the units being used for that purpose. (https://support.google.com/dfp_premium/answer/1191131)
-
-
-
disableInitialLoad
-
This allows for serving companion ad units when the video on the page auto plays. You'll need to include this setting with companionAds as true to avoid possible double impressions. (https://support.google.com/dfp_premium/answer/1191131)
-
-
-
afterEachAdLoaded
-
This is a call back function, see below for more information.
-
-
-
afterAllAdsLoaded
-
This is a call back function, see below for more information.
-
-
-
beforeEachAdLoaded
-
This is a call back function, see below for more information.
-
-
-
-Callbacks
----------
-
-This script provides two callbacks which you can use to make working with DFP a little easier.
-
-
-
-
Callback
-
Parameters
-
Description
-
-
-
afterEachAdLoaded(adUnit)
-
-
-
adUnit - jQuery Object - the jQuery object
-
-
-
This is called after each ad unit has finished rendering.
-
-
-
afterAllAdsLoaded(adUnits)
-
-
-
adUnits - jQuery Object - the jQuery object containing all selected ad units
-
-
-
This is called after all ad units have finished rendering.
-
-
-
alterAdUnitName(adUnitName, adUnit)
-
-
-
adUnitName - String - the default ad unit name
-
adUnit - jQuery Object - the jQuery object
-
-
-
Return the modified or overrided ad unit name. This function is called once per ad unit.
-
-
-
beforeEachAdLoaded(adUnit)
-
-
-
adUnit - jQuery Object - the jQuery object
-
-
-
This is called before each ad unit has started rendering.
-
-
-
afterAdBlocked(adUnit)
-
-
-
adUnit - jQuery Object - the jQuery object
-
-
-
This is called after each AdUnit has been blocked.
-
-
-
-Please see the [example-bootstrap.js](https://github.com/coop182/jquery.dfp.js/blob/master/example-bootstrap.js) file for an example of how to use these.
-
-Default URL Targeting
----------------------
-
-The following targeting options are built into this script and should be setup in your DFP account ([within Inventory/Custom Targeting](https://support.google.com/dfp_sb/bin/answer.py?hl=en&answer=2983838)) to make full use of them. These targeting-parameters can be turned on/off with the setUrlTargeting option.
-
-**Beware: The Targeting string has a 40 character limit!**
-
-
-
-
Key
-
Description
-
-
-
UrlHost
-
This allows you to target different host names, for example you could test your ads on your staging environment before pushing them live by specifying a host of staging.yourdomain.com within DFP, this script will take care of the rest.
-
-
-
UrlPath
-
This allows you to target the path of the users browser, for example if you set UrlPath to '/page1' on the targeting options of the DFP line item it would match http://www.yourdomain.com/page1 only and not http://www.yourdomain.com/page1/segment2.
-
-
-
UrlQuery
-
This allows you to target the query parameters of a page. For example if the URL was http://www.yourdomain.com/page1?param1=value1 you could target it with a DFP ad by specifying a UrlQuery targeting string of param1:value1
-
-
-
-DFP now supports both a "begins with" and a "contains" operator when specifying the custom criteria value. Furthermore the value when using free-form-key-value custom criterias, is no longer subject to a 40 character limit. Read more about custom criteria in the [DFP help](https://support.google.com/dfp_premium/answer/188092).
-
-
-
-**IMPORTANT: Regarding user-identifiable information in url targeting**
-
-If your url contains user-identifiable information you have to anonymize the url when using URL targeting.
-
-From the [DFP docs](https://support.google.com/dfp_premium/answer/177383):
-
-> You may not pass any user-identifiable data (including names, addresses, or user IDs) in the targeting. Please mask this information using the encoding of your choice, and ensure your ad trafficker knows how to decode the values when setting up a line item.
-
-From the [DFP Terms & Conditions](http://www.google.dk/doubleclick/publishers/small-business/terms.html):
-
-> **2.3 Prohibited Actions.** You will not, and will not allow any third party to: ... (h) utilize any feature or functionality of the Program, or include anything in Program Data or Program Ads, that could be so utilized, to personally identify and/or personally track individual end users or any other persons
-
-Ignoring this rule can result in Google shutting down your network!
-
-You can anonymize the url by providing an anonymized version in the 'url' option. This example shows how to replace email occurances in the url with an empty string:
-
-```javascript
-$('selector').dfp({
- dfpID: 'xxxxxxxxx',
- url: window.location.toString().replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/gi, '')
-});
-```
-
-Contributing
-------------
-
-Any and all contributions will be greatly appreciated.
-
-If you wish to you can use [Grunt](http://gruntjs.com/) to enable a smooth contributing and build process.
-
-Install Node.js by running `sudo apt-get install nodejs`
-
-Install Grunt using: `npm install -g grunt-cli`
-
-Once installed run `npm install` from inside the cloned repo directory.
-
-You should now be able to make your changes to `jquery.dfp.js` and once you are finished simply run `grunt` if there are no errors then you can commit your changes and make a pull request and your feature/bug fix will be merged as soon as possible.
-
-Please feel free to write tests which will test your new code, [Travis CI](https://travis-ci.org/) is used to test the code automatically once a pull request is generated.
-
-Thanks a lot to these [contributors](https://github.com/coop182/jquery.dfp.js/graphs/contributors).
diff --git a/js/vendor/jquery.dfp.js/bower.json b/js/vendor/jquery.dfp.js/bower.json
deleted file mode 100644
index 3cd7690..0000000
--- a/js/vendor/jquery.dfp.js/bower.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "name": "jquery.dfp",
- "version": "2.4.1",
- "main": "jquery.dfp.js",
- "ignore": [
- "img/",
- "tests/",
- ".gitattributes",
- ".gitignore",
- ".travis.yml",
- ".vimrc",
- "Gruntfile.js",
- "example-bootstrap.js"
- ]
-}
diff --git a/js/vendor/jquery.dfp.js/dfp.jquery.json b/js/vendor/jquery.dfp.js/dfp.jquery.json
deleted file mode 100644
index ec7c9e3..0000000
--- a/js/vendor/jquery.dfp.js/dfp.jquery.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "name": "dfp",
- "title": "jQuery DFP",
- "description": "A jQuery implementation for Google DoubleClick for Publishers (DFP)",
- "keywords": [
- "DFP",
- "google",
- "ads",
- "advertising"
- ],
- "version": "2.4.1",
- "author": {
- "name": "Matt Cooper",
- "email": "matt@matthewcooper.net",
- "url": "http://matthewcooper.net"
- },
- "homepage": "https://github.com/coop182/jquery.dfp.js",
- "bugs": "https://github.com/coop182/jquery.dfp.js/issues",
- "docs": "https://github.com/coop182/jquery.dfp.js",
- "licenses": [
- {
- "type": "MIT",
- "url": "https://github.com/coop182/jquery.dfp.js/blob/master/MIT-License.txt"
- }
- ],
- "dependencies": {
- "jquery": ">= 1.7"
- }
-}
diff --git a/js/vendor/jquery.dfp.js/jquery.dfp.js b/js/vendor/jquery.dfp.js/jquery.dfp.js
deleted file mode 100644
index 89762f1..0000000
--- a/js/vendor/jquery.dfp.js/jquery.dfp.js
+++ /dev/null
@@ -1,646 +0,0 @@
-/**
- * jQuery DFP v2.4.1
- * http://github.com/coop182/jquery.dfp.js
- *
- * Copyright 2015 Matt Cooper
- * Released under the MIT license
- */
-
-(function (window, undefined) {
- "use strict";
-
- /**
- * Make plugin UMD compatible
- * Uses CommonJS, AMD or browser globals to create plugin.
- */
- (function (factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define( ['jquery'], factory );
- } else if (typeof exports === 'object') {
- // Node/CommonJS
- factory( require( 'jquery' ) );
- } else {
- // Browser globals
- factory( window.jQuery || window.Zepto );
- }
- }(function ($) {
-
- var
-
- // Save Scope
- dfpScript = this || {};
-
- var
- // DFP account ID
- dfpID = '',
-
- // Init counters
- count = 0,
- uid = 0,
- rendered = 0,
-
- // Default DFP selector
- dfpSelector = '.adunit',
-
- adsCouldNeverBeInitilized = false,
-
- // Keep track of if we've already tried to load gpt.js before
- dfpIsLoaded = false,
-
- // Store adunit on div as:
- storeAs = 'googleAdUnit',
-
- /**
- * Init function sets required params and loads Google's DFP script
- * @param String id The DFP account ID
- * @param String selector The adunit selector
- * @param Object options Custom options to apply
- */
- init = function (id, selector, options) {
- var $adCollection;
-
- // Reset counters on each call
- count = 0;
- rendered = 0;
-
- dfpID = id;
- $adCollection = $( selector );
-
- /**
- * @returns {boolean}
- */
- dfpScript.shouldCheckForAdBlockers = function(){
- return options ? typeof options.afterAdBlocked === 'function' : false;
- };
-
- // explicitly wait for loader to be completed, otherwise the googletag might not be available
- dfpLoader( options, $adCollection ).then(function(){
- options = setOptions( options );
- dfpScript.dfpOptions = options;
-
- $(function () {
- createAds( options, $adCollection );
- displayAds( options, $adCollection );
- });
- });
-
- },
-
- /**
- * Set the options for DFP
- * @param Object options Custom options to apply
- * @return Object extended options
- */
- setOptions = function (options) {
-
- // Set default options
- var dfpOptions = {
- setTargeting: {},
- setCategoryExclusion: '',
- setLocation: '',
- enableSingleRequest: true,
- collapseEmptyDivs: 'original',
- refreshExisting: true,
- disablePublisherConsole: false,
- disableInitialLoad: false,
- noFetch: false,
- namespace: undefined,
- sizeMapping: {}
- };
-
- if (typeof options.setUrlTargeting === 'undefined' || options.setUrlTargeting) {
- // Get URL Targeting
- var urlTargeting = getUrlTargeting( options.url );
- $.extend(true, dfpOptions.setTargeting, {
- UrlHost: urlTargeting.Host,
- UrlPath: urlTargeting.Path,
- UrlQuery: urlTargeting.Query
- });
- }
-
- // Merge options objects
- $.extend( true, dfpOptions, options );
-
- // If a custom googletag is specified, use it.
- if (dfpOptions.googletag) {
- window.googletag.cmd.push(function () {
- $.extend( true, window.googletag, dfpOptions.googletag );
- });
- }
-
- return dfpOptions;
- },
-
- /**
- * Find and create all Ads
- * @param Object dfpOptions options related to ad instantiation
- * @param jQuery $adCollection collection of ads
- * @return Array an array of ad units that have been created.
- */
- createAds = function (dfpOptions, $adCollection) {
- var googletag = window.googletag;
- // Loops through on page Ad units and gets ads for them.
- $adCollection.each(function () {
- var $adUnit = $( this );
-
- count++;
-
- // adUnit name
- var adUnitName = getName( $adUnit, dfpOptions );
-
- // adUnit id - this will use an existing id or an auto generated one.
- var adUnitID = getID( $adUnit, adUnitName );
-
- // get dimensions of the adUnit
- var dimensions = getDimensions( $adUnit );
-
- // set existing content
- $adUnit.data( 'existingContent', $adUnit.html() );
-
- // wipe html clean ready for ad and set the default display class.
- $adUnit.html( '' ).addClass( 'display-none' );
-
- // Push commands to DFP to create ads
- googletag.cmd.push(function () {
-
- var googleAdUnit,
- $adUnitData = $adUnit.data( storeAs );
-
- if ($adUnitData) {
-
- // Get existing ad unit
- googleAdUnit = $adUnitData;
-
- } else {
-
- // Build slotName for loading
- var slotName;
- if (dfpID === '') {
- slotName = adUnitName;
- } else {
- slotName = '/' + dfpID + '/' + adUnitName;
- }
-
- // Create the ad - out of page or normal
- if ($adUnit.data( 'outofpage' )) {
- googleAdUnit = googletag.defineOutOfPageSlot( slotName, adUnitID );
- } else {
- googleAdUnit = googletag.defineSlot( slotName, dimensions, adUnitID );
- if ($adUnit.data( 'companion' )) {
- googleAdUnit = googleAdUnit.addService( googletag.companionAds() );
- }
- }
-
- googleAdUnit = googleAdUnit.addService( googletag.pubads() );
-
- }
-
- // Sets custom targeting for just THIS ad unit if it has been specified
- var targeting = $adUnit.data( 'targeting' );
- if (targeting) {
- $.each(targeting, function (k, v) {
- googleAdUnit.setTargeting( k, v );
- });
- }
-
- // Sets custom exclusions for just THIS ad unit if it has been specified
- var exclusions = $adUnit.data( 'exclusions' );
- if (exclusions) {
- var exclusionsGroup = exclusions.split( ',' );
- var valueTrimmed;
- $.each(exclusionsGroup, function (k, v) {
- valueTrimmed = $.trim( v );
- if (valueTrimmed.length > 0) {
- googleAdUnit.setCategoryExclusion( valueTrimmed );
- }
- });
- }
-
- // Sets responsive size mapping for just THIS ad unit if it has been specified
- var mapping = $adUnit.data( 'size-mapping' );
- if (mapping && dfpOptions.sizeMapping[mapping]) {
- // Convert verbose to DFP format
- var map = googletag.sizeMapping();
- $.each(dfpOptions.sizeMapping[mapping], function (k, v) {
- map.addSize( v.browser, v.ad_sizes );
- });
- googleAdUnit.defineSizeMapping( map.build() );
- }
-
- // Store googleAdUnit reference
- $adUnit.data( storeAs, googleAdUnit );
-
- // Allow altering of the ad slot before ad load
- if (typeof dfpOptions.beforeEachAdLoaded === 'function') {
- dfpOptions.beforeEachAdLoaded.call( this, $adUnit );
- }
- });
-
- });
-
- // Push DFP config options
- googletag.cmd.push(function () {
-
- var pubadsService = googletag.pubads();
-
- if (dfpOptions.enableSingleRequest) {
- pubadsService.enableSingleRequest();
- }
-
- $.each(dfpOptions.setTargeting, function (k, v) {
- pubadsService.setTargeting( k, v );
- });
-
- var setLocation = dfpOptions.setLocation;
- if (typeof setLocation === 'object') {
- if (typeof setLocation.latitude === 'number' && typeof setLocation.longitude === 'number' &&
- typeof setLocation.precision === 'number') {
- pubadsService.setLocation( setLocation.latitude, setLocation.longitude, setLocation.precision );
- } else if (typeof setLocation.latitude === 'number' && typeof setLocation.longitude === 'number') {
- pubadsService.setLocation( setLocation.latitude, setLocation.longitude );
- }
- }
-
- if (dfpOptions.setCategoryExclusion.length > 0) {
- var exclusionsGroup = dfpOptions.setCategoryExclusion.split( ',' );
- var valueTrimmed;
-
- $.each(exclusionsGroup, function (k, v) {
- valueTrimmed = $.trim( v );
- if (valueTrimmed.length > 0) {
- pubadsService.setCategoryExclusion( valueTrimmed );
- }
- });
- }
-
- if (dfpOptions.collapseEmptyDivs) {
- pubadsService.collapseEmptyDivs();
- }
-
- if (dfpOptions.disablePublisherConsole) {
- pubadsService.disablePublisherConsole();
- }
-
- if (dfpOptions.companionAds) {
- googletag.companionAds().setRefreshUnfilledSlots( true );
-
- if ( ! dfpOptions.disableInitialLoad) {
- pubadsService.enableVideoAds();
- }
- }
-
- if (dfpOptions.disableInitialLoad) {
- pubadsService.disableInitialLoad();
- }
-
- if (dfpOptions.noFetch) {
- pubadsService.noFetch();
- }
-
- // Setup event listener to listen for renderEnded event and fire callbacks.
- pubadsService.addEventListener('slotRenderEnded', function (event) {
-
- rendered++;
-
- var $adUnit = $( '#' + event.slot.getSlotId().getDomId() );
-
- var display = event.isEmpty ? 'none' : 'block';
-
- // if the div has been collapsed but there was existing content expand the
- // div and reinsert the existing content.
- var $existingContent = $adUnit.data( 'existingContent' );
- if (display === 'none' && $.trim( $existingContent ).length > 0 &&
- dfpOptions.collapseEmptyDivs === 'original') {
- $adUnit.show().html( $existingContent );
- display = 'block display-original';
- }
-
- $adUnit.removeClass( 'display-none' ).addClass( 'display-' + display );
-
- // Excute afterEachAdLoaded callback if provided
- if (typeof dfpOptions.afterEachAdLoaded === 'function') {
- dfpOptions.afterEachAdLoaded.call( this, $adUnit, event );
- }
-
- // Excute afterAllAdsLoaded callback if provided
- if (typeof dfpOptions.afterAllAdsLoaded === 'function' && rendered === count) {
- dfpOptions.afterAllAdsLoaded.call( this, $adCollection );
- }
-
- });
-
- // this will work with AdblockPlus
- if (dfpScript.shouldCheckForAdBlockers() && ! googletag._adBlocked_) {
- setTimeout(function () {
- var slots = pubadsService.getSlots ? pubadsService.getSlots() : [];
- if (slots.length > 0) {
- $.get( slots[0].getContentUrl() ).always(function (r) {
- if (r.status !== 200) {
- $.each(slots, function () {
- var $adUnit = $( '#' + this.getSlotId().getDomId() );
- dfpOptions.afterAdBlocked.call( dfpScript, $adUnit, this );
- });
- }
- });
- }
- }, 0);
- }
-
- googletag.enableServices();
-
- });
-
- },
-
- /**
- * Display all created Ads
- * @param {Object} dfpOptions options related to ad instantiation
- * @param {jQuery} $adCollection collection of ads
- */
- displayAds = function (dfpOptions, $adCollection) {
-
- var googletag = window.googletag;
- // Check if google adLoader can be loaded, this will work with AdBlock
- if (dfpScript.shouldCheckForAdBlockers() && ! googletag._adBlocked_) {
- if (googletag.getVersion) {
- var script = '//partner.googleadservices.com/gpt/pubads_impl_' +
- googletag.getVersion() + '.js';
- $.getScript( script ).always(function (r) {
- if (r && r.statusText === 'error') {
- $.each($adCollection, function () {
- dfpOptions.afterAdBlocked.call( dfpScript, $( this ) );
- });
- }
- });
- }
-
- }
-
- $adCollection.each(function () {
-
- var $adUnit = $( this ),
- $adUnitData = $adUnit.data( storeAs );
-
- if (googletag._adBlocked_) {
- if (dfpScript.shouldCheckForAdBlockers()) {
- dfpOptions.afterAdBlocked.call( dfpScript, $adUnit );
- }
- }
- if (dfpOptions.refreshExisting && $adUnitData && $adUnit.hasClass( 'display-block' )) {
-
- googletag.cmd.push( function () { googletag.pubads().refresh( [$adUnitData] ); } );
-
- } else {
- googletag.cmd.push( function () { googletag.display( $adUnit.attr( 'id' ) ); } );
- }
-
- });
-
- },
-
- /**
- * Create an array of paths so that we can target DFP ads to Page URI's
- * @return Array an array of URL parts that can be targeted.
- */
- getUrlTargeting = function (url) {
-
- // Get the url and parse it to its component parts using regex from RFC2396 Appendix-B (https://tools.ietf.org/html/rfc2396#appendix-B)
- var urlMatches = (url || window.location.toString()).match( / ^(([^: / ?#] + ):)?(\ / \ / ([^ / ?#] * ))?([^?#] * )(\?([^#] * ))?(#( .* ))? / );
- var matchedAuthority = urlMatches[4] || '';
- var matchedPath = (urlMatches[5] || '').replace( /(.)\/$/, '$1' );
- var matchedQuery = urlMatches[7] || '';
-
- // Get the query params for targeting against
- var params = matchedQuery.replace( /\=/ig, ':' ).split( '&' );
-
- return {
- Host: matchedAuthority,
- Path: matchedPath,
- Query: params
- };
-
- },
-
- /**
- * Get the id of the adUnit div or generate a unique one.
- * @param Object $adUnit The adunit to work with
- * @param String adUnitName The name of the adunit
- * @return String The ID of the adunit or a unique autogenerated ID
- */
- getID = function ($adUnit, adUnitName) {
-
- uid++;
- return $adUnit.attr( 'id' ) || $adUnit.attr( 'id', adUnitName.replace( /[^A-z0-9]/g, '_' ) + '-auto-gen-id-' + uid ).attr( 'id' );
-
- },
-
- /**
- * Get the name of the Ad unit, either use the div id or
- * check for the optional attribute data-adunit
- * @param Object $adUnit The adunit to work with
- * @param Object dfpOptions options related to ad instantiation
- * @return String The name of the adunit, will be the same as inside DFP
- */
- getName = function ($adUnit, dfpOptions) {
-
- var adUnitName = $adUnit.data( 'adunit' ) || dfpOptions.namespace || $adUnit.attr( 'id' ) || '';
- if (typeof dfpOptions.alterAdUnitName === 'function') {
- adUnitName = dfpOptions.alterAdUnitName.call( this, adUnitName, $adUnit );
- }
- return adUnitName;
-
- },
-
- /**
- * Get the dimensions of the ad unit using the container div dimensions or
- * check for the optional attribute data-dimensions
- * @param Object $adUnit The adunit to work with
- * @return Array The dimensions of the adunit (width, height)
- */
- getDimensions = function ($adUnit) {
-
- var dimensions = [],
- dimensionsData = $adUnit.data( 'dimensions' );
-
- // Check if data-dimensions are specified. If they aren't, use the dimensions of the ad unit div.
- if (dimensionsData) {
-
- var dimensionGroups = dimensionsData.split( ',' );
-
- $.each(dimensionGroups, function (k, v) {
-
- var dimensionSet = v.split( 'x' );
- dimensions.push( [parseInt( dimensionSet[0], 10 ), parseInt( dimensionSet[1], 10 )] );
-
- });
-
- } else {
-
- dimensions.push( [$adUnit.width(), $adUnit.height()] );
-
- }
-
- return dimensions;
-
- },
-
- /**
- * Call the google DFP script - there is a little bit of error detection in here to detect
- * if the dfp script has failed to load either through an error or it being blocked by an ad
- * blocker... if it does not load we execute a dummy script to replace the real DFP.
- *
- * @param {Object} options
- * @param {Array} $adCollection
- */
- dfpLoader = function (options, $adCollection) {
-
- function execBlockEvents() {
- if (dfpScript.shouldCheckForAdBlockers()) {
- $.each($adCollection, function () {
- options.afterAdBlocked.call( dfpScript, $( this ) );
- });
- }
- }
-
- // make sure we don't load gpt.js multiple times
- dfpIsLoaded = dfpIsLoaded || $( 'script[src*="googletagservices.com/tag/js/gpt.js"]' ).length;
- if (dfpIsLoaded) {
- if (adsCouldNeverBeInitilized) {
- execBlockEvents();
- }
- return $.Deferred().resolve();
- }
-
- var loaded = $.Deferred();
-
- window.googletag = window.googletag || {};
- window.googletag.cmd = window.googletag.cmd || [];
-
- var gads = document.createElement( 'script' );
- gads.async = true;
- gads.type = 'text/javascript';
-
- // Adblock blocks the load of Ad scripts... so we check for that
- gads.onerror = function () {
- dfpBlocked();
- loaded.resolve();
- adsCouldNeverBeInitilized = true;
- execBlockEvents();
- };
-
- gads.onload = function() {
- // this will work with ghostery:
- if ( ! googletag._loadStarted_) {
- googletag._adBlocked_ = true;
- execBlockEvents();
- }
- loaded.resolve();
- };
-
- var useSSL = 'https:' === document.location.protocol;
- gads.src = (useSSL ? 'https:' : 'http:') +
- '//www.googletagservices.com/tag/js/gpt.js';
- var node = document.getElementsByTagName( 'script' )[0];
- node.parentNode.insertBefore( gads, node );
-
- // Adblock plus seems to hide blocked scripts... so we check for that
- if (gads.style.display === 'none') {
- dfpBlocked();
- }
-
- return loaded;
-
- },
-
- /**
- * This function gets called if DFP has been blocked by an adblocker
- * it implements a dummy version of the dfp object and allows the script to excute its callbacks
- * regardless of whether DFP is actually loaded or not... it is basically only useful for situations
- * where you are laying DFP over existing content and need to init things like slide shows after the loading
- * is completed.
- */
- dfpBlocked = function () {
- var googletag = window.googletag;
- // Get the stored dfp commands
- var commands = googletag.cmd;
-
- var _defineSlot = function (name, dimensions, id, oop) {
- googletag.ads.push( id );
- googletag.ads[id] = {
- renderEnded: function () { },
- addService: function () { return this; }
- };
-
- return googletag.ads[id];
- };
-
- // overwrite the dfp object - replacing the command array with a function and defining missing functions
- googletag = {
- cmd: {
- push: function (callback) {
- callback.call( dfpScript );
- }
- },
- ads: [],
- pubads: function () { return this; },
- noFetch: function () { return this; },
- disableInitialLoad: function () { return this; },
- disablePublisherConsole: function () { return this; },
- enableSingleRequest: function () { return this; },
- setTargeting: function () { return this; },
- collapseEmptyDivs: function () { return this; },
- enableServices: function () { return this; },
- defineSlot: function (name, dimensions, id) {
- return _defineSlot( name, dimensions, id, false );
- },
- defineOutOfPageSlot: function (name, id) {
- return _defineSlot( name, [], id, true );
- },
- display: function (id) {
- googletag.ads[id].renderEnded.call( dfpScript );
- return this;
- }
-
- };
-
- // Execute any stored commands
- $.each(commands, function (k, v) {
- googletag.cmd.push( v );
- });
-
- };
-
- /**
- * Add function to the jQuery / Zepto namespace
- * @param String id (Optional) The DFP account ID
- * @param Object options (Optional) Custom options to apply
- */
- $.dfp = $.fn.dfp = function (id, options) {
-
- options = options || {};
-
- if (id === undefined) {
- id = dfpID;
- }
-
- if (typeof id === 'object') {
- options = id;
- id = options.dfpID || dfpID;
- }
-
- var selector = this;
-
- if (typeof this === 'function') {
- selector = dfpSelector;
- }
-
- init( id, selector, options );
-
- return this;
-
- };
-
- }));
-
-})(window);
diff --git a/js/vendor/jquery.dfp.js/jquery.dfp.min.js b/js/vendor/jquery.dfp.js/jquery.dfp.min.js
deleted file mode 100644
index ec7fbda..0000000
--- a/js/vendor/jquery.dfp.js/jquery.dfp.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * jQuery DFP v2.4.1
- * http://github.com/coop182/jquery.dfp.js
- *
- * Copyright 2015 Matt Cooper
- * Released under the MIT license
- */
-!function(a,b){"use strict";!function(b){"function"==typeof define&&define.amd?define(["jquery"],b):b("object"==typeof exports?require("jquery"):a.jQuery||a.Zepto)}(function(c){var d=this||{},e="",f=0,g=0,h=0,i=".adunit",j=!1,k=!1,l="googleAdUnit",m=function(a,b,g){var i;f=0,h=0,e=a,i=c(b),d.shouldCheckForAdBlockers=function(){return g?"function"==typeof g.afterAdBlocked:!1},u(g,i).then(function(){g=n(g),d.dfpOptions=g,c(function(){o(g,i),p(g,i)})})},n=function(d){var e={setTargeting:{},setCategoryExclusion:"",setLocation:"",enableSingleRequest:!0,collapseEmptyDivs:"original",refreshExisting:!0,disablePublisherConsole:!1,disableInitialLoad:!1,noFetch:!1,namespace:b,sizeMapping:{}};if("undefined"==typeof d.setUrlTargeting||d.setUrlTargeting){var f=q(d.url);c.extend(!0,e.setTargeting,{UrlHost:f.Host,UrlPath:f.Path,UrlQuery:f.Query})}return c.extend(!0,e,d),e.googletag&&a.googletag.cmd.push(function(){c.extend(!0,a.googletag,e.googletag)}),e},o=function(b,g){var i=a.googletag;g.each(function(){var a=c(this);f++;var d=s(a,b),g=r(a,d),h=t(a);a.data("existingContent",a.html()),a.html("").addClass("display-none"),i.cmd.push(function(){var f,j=a.data(l);if(j)f=j;else{var k;k=""===e?d:"/"+e+"/"+d,a.data("outofpage")?f=i.defineOutOfPageSlot(k,g):(f=i.defineSlot(k,h,g),a.data("companion")&&(f=f.addService(i.companionAds()))),f=f.addService(i.pubads())}var m=a.data("targeting");m&&c.each(m,function(a,b){f.setTargeting(a,b)});var n=a.data("exclusions");if(n){var o,p=n.split(",");c.each(p,function(a,b){o=c.trim(b),o.length>0&&f.setCategoryExclusion(o)})}var q=a.data("size-mapping");if(q&&b.sizeMapping[q]){var r=i.sizeMapping();c.each(b.sizeMapping[q],function(a,b){r.addSize(b.browser,b.ad_sizes)}),f.defineSizeMapping(r.build())}a.data(l,f),"function"==typeof b.beforeEachAdLoaded&&b.beforeEachAdLoaded.call(this,a)})}),i.cmd.push(function(){var a=i.pubads();b.enableSingleRequest&&a.enableSingleRequest(),c.each(b.setTargeting,function(b,c){a.setTargeting(b,c)});var e=b.setLocation;if("object"==typeof e&&("number"==typeof e.latitude&&"number"==typeof e.longitude&&"number"==typeof e.precision?a.setLocation(e.latitude,e.longitude,e.precision):"number"==typeof e.latitude&&"number"==typeof e.longitude&&a.setLocation(e.latitude,e.longitude)),b.setCategoryExclusion.length>0){var j,k=b.setCategoryExclusion.split(",");c.each(k,function(b,d){j=c.trim(d),j.length>0&&a.setCategoryExclusion(j)})}b.collapseEmptyDivs&&a.collapseEmptyDivs(),b.disablePublisherConsole&&a.disablePublisherConsole(),b.companionAds&&(i.companionAds().setRefreshUnfilledSlots(!0),b.disableInitialLoad||a.enableVideoAds()),b.disableInitialLoad&&a.disableInitialLoad(),b.noFetch&&a.noFetch(),a.addEventListener("slotRenderEnded",function(a){h++;var d=c("#"+a.slot.getSlotId().getDomId()),e=a.isEmpty?"none":"block",i=d.data("existingContent");"none"===e&&c.trim(i).length>0&&"original"===b.collapseEmptyDivs&&(d.show().html(i),e="block display-original"),d.removeClass("display-none").addClass("display-"+e),"function"==typeof b.afterEachAdLoaded&&b.afterEachAdLoaded.call(this,d,a),"function"==typeof b.afterAllAdsLoaded&&h===f&&b.afterAllAdsLoaded.call(this,g)}),d.shouldCheckForAdBlockers()&&!i._adBlocked_&&setTimeout(function(){var e=a.getSlots?a.getSlots():[];e.length>0&&c.get(e[0].getContentUrl()).always(function(a){200!==a.status&&c.each(e,function(){var a=c("#"+this.getSlotId().getDomId());b.afterAdBlocked.call(d,a,this)})})},0),i.enableServices()})},p=function(b,e){var f=a.googletag;if(d.shouldCheckForAdBlockers()&&!f._adBlocked_&&f.getVersion){var g="//partner.googleadservices.com/gpt/pubads_impl_"+f.getVersion()+".js";c.getScript(g).always(function(a){a&&"error"===a.statusText&&c.each(e,function(){b.afterAdBlocked.call(d,c(this))})})}e.each(function(){var a=c(this),e=a.data(l);f._adBlocked_&&d.shouldCheckForAdBlockers()&&b.afterAdBlocked.call(d,a),f.cmd.push(b.refreshExisting&&e&&a.hasClass("display-block")?function(){f.pubads().refresh([e])}:function(){f.display(a.attr("id"))})})},q=function(b){var c=(b||a.location.toString()).match(/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/),d=c[4]||"",e=(c[5]||"").replace(/(.)\/$/,"$1"),f=c[7]||"",g=f.replace(/\=/gi,":").split("&");return{Host:d,Path:e,Query:g}},r=function(a,b){return g++,a.attr("id")||a.attr("id",b.replace(/[^A-z0-9]/g,"_")+"-auto-gen-id-"+g).attr("id")},s=function(a,b){var c=a.data("adunit")||b.namespace||a.attr("id")||"";return"function"==typeof b.alterAdUnitName&&(c=b.alterAdUnitName.call(this,c,a)),c},t=function(a){var b=[],d=a.data("dimensions");if(d){var e=d.split(",");c.each(e,function(a,c){var d=c.split("x");b.push([parseInt(d[0],10),parseInt(d[1],10)])})}else b.push([a.width(),a.height()]);return b},u=function(b,e){function f(){d.shouldCheckForAdBlockers()&&c.each(e,function(){b.afterAdBlocked.call(d,c(this))})}if(k=k||c('script[src*="googletagservices.com/tag/js/gpt.js"]').length)return j&&f(),c.Deferred().resolve();var g=c.Deferred();a.googletag=a.googletag||{},a.googletag.cmd=a.googletag.cmd||[];var h=document.createElement("script");h.async=!0,h.type="text/javascript",h.onerror=function(){v(),g.resolve(),j=!0,f()},h.onload=function(){googletag._loadStarted_||(googletag._adBlocked_=!0,f()),g.resolve()};var i="https:"===document.location.protocol;h.src=(i?"https:":"http:")+"//www.googletagservices.com/tag/js/gpt.js";var l=document.getElementsByTagName("script")[0];return l.parentNode.insertBefore(h,l),"none"===h.style.display&&v(),g},v=function(){var b=a.googletag,e=b.cmd,f=function(a,c,d,e){return b.ads.push(d),b.ads[d]={renderEnded:function(){},addService:function(){return this}},b.ads[d]};b={cmd:{push:function(a){a.call(d)}},ads:[],pubads:function(){return this},noFetch:function(){return this},disableInitialLoad:function(){return this},disablePublisherConsole:function(){return this},enableSingleRequest:function(){return this},setTargeting:function(){return this},collapseEmptyDivs:function(){return this},enableServices:function(){return this},defineSlot:function(a,b,c){return f(a,b,c,!1)},defineOutOfPageSlot:function(a,b){return f(a,[],b,!0)},display:function(a){return b.ads[a].renderEnded.call(d),this}},c.each(e,function(a,c){b.cmd.push(c)})};c.dfp=c.fn.dfp=function(a,c){c=c||{},a===b&&(a=e),"object"==typeof a&&(c=a,a=c.dfpID||e);var d=this;return"function"==typeof this&&(d=i),m(a,d,c),this}})}(window);
\ No newline at end of file
diff --git a/js/vendor/jquery.dfp.js/package.json b/js/vendor/jquery.dfp.js/package.json
deleted file mode 100644
index 0b6b72c..0000000
--- a/js/vendor/jquery.dfp.js/package.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "name": "jquery.dfp",
- "version": "2.4.1",
- "devDependencies": {
- "grunt": "~0.4",
- "grunt-contrib-jasmine": "^0.8.2",
- "grunt-contrib-jshint": "^0.11.1",
- "grunt-contrib-uglify": "^0.8.0"
- },
- "scripts": {
- "test": "grunt travis --verbose"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/coop182/jquery.dfp.js"
- },
- "main": "jquery.dfp.js"
-}
diff --git a/js/vendor/jquery.dfp.min.js b/js/vendor/jquery.dfp.min.js
deleted file mode 100644
index 9d6b7f9..0000000
--- a/js/vendor/jquery.dfp.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * jQuery DFP v1.1.5
- * http://github.com/coop182/jquery.dfp.js
- *
- * Copyright 2014 Matt Cooper
- * Released under the MIT license
- */
-!function(a,b,c){"use strict";var d,e=this,f="",g=0,h=0,i=0,j=".adunit",k={},l=!1,m="googleAdUnit",n=function(b,c,e){g=0,i=0,f=b,d=a(c),v(),o(e),a(function(){p(),q()})},o=function(d){if(k={setTargeting:{},setCategoryExclusion:"",setLocation:"",enableSingleRequest:!0,collapseEmptyDivs:"original",refreshExisting:!0,disablePublisherConsole:!1,disableInitialLoad:!1,noFetch:!1,namespace:c,sizeMapping:{}},"undefined"==typeof d.setUrlTargeting||d.setUrlTargeting){var e=r();a.extend(!0,k.setTargeting,{inURL:e.inURL,URLIs:e.URLIs,Query:e.Query,Domain:b.location.host})}a.extend(!0,k,d),k.googletag&&b.googletag.cmd.push(function(){a.extend(!0,b.googletag,k.googletag)})},p=function(){d.each(function(){var c=a(this);g++;var d=t(c),e=s(c,d),h=u(c);c.data("existingContent",c.html()),c.html("").addClass("display-none"),b.googletag.cmd.push(function(){var g,i=c.data(m);g=i?i:c.data("outofpage")?b.googletag.defineOutOfPageSlot("/"+f+"/"+d,e).addService(b.googletag.pubads()):c.data("companion")?b.googletag.defineSlot("/"+f+"/"+d,h,e).addService(b.googletag.companionAds()).addService(b.googletag.pubads()):b.googletag.defineSlot("/"+f+"/"+d,h,e).addService(b.googletag.pubads());var j=c.data("targeting");j&&a.each(j,function(a,b){g.setTargeting(a,b)});var l=c.data("exclusions");if(l){var n,o=l.split(",");a.each(o,function(b,c){n=a.trim(c),n.length>0&&g.setCategoryExclusion(n)})}var p=c.data("size-mapping");if(p&&k.sizeMapping[p]){var q=b.googletag.sizeMapping();a.each(k.sizeMapping[p],function(a,b){q.addSize(b.browser,b.ad_sizes)}),g.defineSizeMapping(q.build())}c.data(m,g),"function"==typeof k.beforeEachAdLoaded&&k.beforeEachAdLoaded.call(this,c)})}),b.googletag.cmd.push(function(){if(k.enableSingleRequest&&b.googletag.pubads().enableSingleRequest(),a.each(k.setTargeting,function(a,c){b.googletag.pubads().setTargeting(a,c)}),"object"==typeof k.setLocation&&("number"==typeof k.setLocation.latitude&&"number"==typeof k.setLocation.longitude&&"number"==typeof k.setLocation.precision?b.googletag.pubads().setLocation(k.setLocation.latitude,k.setLocation.longitude,k.setLocation.precision):"number"==typeof k.setLocation.latitude&&"number"==typeof k.setLocation.longitude&&b.googletag.pubads().setLocation(k.setLocation.latitude,k.setLocation.longitude)),k.setCategoryExclusion.length>0){var c,e=k.setCategoryExclusion.split(",");a.each(e,function(d,e){c=a.trim(e),c.length>0&&b.googletag.pubads().setCategoryExclusion(c)})}k.collapseEmptyDivs&&b.googletag.pubads().collapseEmptyDivs(),k.disablePublisherConsole&&b.googletag.pubads().disablePublisherConsole(),k.companionAds&&(b.googletag.companionAds().setRefreshUnfilledSlots(!0),k.disableInitialLoad||b.googletag.pubads().enableVideoAds()),k.disableInitialLoad&&b.googletag.pubads().disableInitialLoad(),k.noFetch&&b.googletag.pubads().noFetch(),b.googletag.pubads().addEventListener("slotRenderEnded",function(b){i++;var c=a("#"+b.slot.getSlotId().getDomId()),e=b.isEmpty?"none":"block",f=c.data("existingContent");"none"===e&&a.trim(f).length>0&&"original"===k.collapseEmptyDivs&&(c.show().html(f),e="block display-original"),c.removeClass("display-none").addClass("display-"+e),"function"==typeof k.afterEachAdLoaded&&k.afterEachAdLoaded.call(this,c,b),"function"==typeof k.afterAllAdsLoaded&&i===g&&k.afterAllAdsLoaded.call(this,d)}),b.googletag.enableServices()})},q=function(){d.each(function(){var c=a(this),d=c.data(m);b.googletag.cmd.push(k.refreshExisting&&d&&c.hasClass("display-block")?function(){b.googletag.pubads().refresh([d])}:function(){b.googletag.display(c.attr("id"))})})},r=function(){var a=b.location.pathname.replace(/\/$/,""),c=new RegExp("/([^/]*)","ig"),d=a.match(c),e=["/"],f="";if(d&&"/"!==a){var g="",h=d.length;if(h>0)for(var i=0;h>i;i++){g=d[i],e.push(g);for(var j=i+1;h>j;j++)g+=d[j],e.push(g);0===i&&(e.splice(-1,1),f=g)}e.push(f)}e=e.reverse();var k=(b.location.toString().replace(/\=/gi,":").match(/\?(.+)$/),RegExp.$1.split("&"));return{inURL:e,URLIs:e[0],Query:k}},s=function(a,b){return h++,a.attr("id")||a.attr("id",b.replace(/[^A-z0-9]/g,"_")+"-auto-gen-id-"+h).attr("id")},t=function(a){var b=a.data("adunit")||k.namespace||a.attr("id")||"";return"function"==typeof k.alterAdUnitName&&(b=k.alterAdUnitName.call(this,b,a)),b},u=function(b){var c=[],d=b.data("dimensions");if(d){var e=d.split(",");a.each(e,function(a,b){var d=b.split("x");c.push([parseInt(d[0],10),parseInt(d[1],10)])})}else c.push([b.width(),b.height()]);return c},v=function(){if(l=l||a('script[src*="googletagservices.com/tag/js/gpt.js"]').length,!l){b.googletag=b.googletag||{},b.googletag.cmd=b.googletag.cmd||[];var c=document.createElement("script");c.async=!0,c.type="text/javascript",c.onerror=function(){w()};var d="https:"===document.location.protocol;c.src=(d?"https:":"http:")+"//www.googletagservices.com/tag/js/gpt.js";var e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(c,e),"none"===c.style.display&&w()}},w=function(){var c=b.googletag.cmd;setTimeout(function(){var d=function(a,c,d){return b.googletag.ads.push(d),b.googletag.ads[d]={renderEnded:function(){},addService:function(){return this}},b.googletag.ads[d]};b.googletag={cmd:{push:function(a){a.call(e)}},ads:[],pubads:function(){return this},noFetch:function(){return this},disableInitialLoad:function(){return this},disablePublisherConsole:function(){return this},enableSingleRequest:function(){return this},setTargeting:function(){return this},collapseEmptyDivs:function(){return this},enableServices:function(){return this},defineSlot:function(a,b,c){return d(a,b,c,!1)},defineOutOfPageSlot:function(a,b){return d(a,[],b,!0)},display:function(a){return b.googletag.ads[a].renderEnded.call(e),this}},a.each(c,function(a,c){b.googletag.cmd.push(c)})},50)};a.dfp=a.fn.dfp=function(a,b){b=b||{},a===c&&(a=f),"object"==typeof a&&(b=a,a=b.dfpID||f);var d=this;return"function"==typeof this&&(d=j),n(a,d,b),this}}(window.jQuery||window.Zepto||window.tire,window);
\ No newline at end of file
diff --git a/boilerplate/languages b/languages
similarity index 100%
rename from boilerplate/languages
rename to languages
diff --git a/license.txt b/license.txt
deleted file mode 100644
index fa02ff1..0000000
--- a/license.txt
+++ /dev/null
@@ -1,280 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
diff --git a/mkdocs.yml b/mkdocs.yml
deleted file mode 100644
index 79c3e3c..0000000
--- a/mkdocs.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-site_name: DoubleClick for WordPress
-theme: readthedocs
diff --git a/boilerplate/package.json b/package.json
similarity index 100%
rename from boilerplate/package.json
rename to package.json
diff --git a/boilerplate/phpcs.xml b/phpcs.xml
similarity index 100%
rename from boilerplate/phpcs.xml
rename to phpcs.xml
diff --git a/boilerplate/phpunit.xml b/phpunit.xml
similarity index 100%
rename from boilerplate/phpunit.xml
rename to phpunit.xml
diff --git a/boilerplate/release.sh b/release.sh
similarity index 100%
rename from boilerplate/release.sh
rename to release.sh
diff --git a/boilerplate/tests/bootstrap.php b/tests/bootstrap.php
similarity index 100%
rename from boilerplate/tests/bootstrap.php
rename to tests/bootstrap.php
diff --git a/boilerplate/tests/test-base.php b/tests/test-base.php
similarity index 100%
rename from boilerplate/tests/test-base.php
rename to tests/test-base.php
diff --git a/tests/test-doubleclick.php b/tests/test-doubleclick.php
new file mode 100644
index 0000000..2277ace
--- /dev/null
+++ b/tests/test-doubleclick.php
@@ -0,0 +1,36 @@
+assertTrue( class_exists( 'DCWP_Options') );
+ }
+
+ /**
+ * Test that we can access our class through our helper function.
+ *
+ * @since 0.2.1
+ */
+ function test_class_access() {
+ $this->assertInstanceOf( 'DCWP_Options', doubleclick_for_wordpress()->options );
+ }
+
+ /**
+ * Replace this with some actual testing code.
+ *
+ * @since 0.2.1
+ */
+ function test_sample() {
+ $this->assertTrue( true );
+ }
+}
From 27e5e28065efc126db31c41a93e8fd2ac20928ba Mon Sep 17 00:00:00 2001
From: rclations
Date: Thu, 22 Jun 2017 18:09:04 -0400
Subject: [PATCH 03/41] wip on migrating options page
---
includes/class-options.php | 152 +++++++++++++++++++++++++++++++++++--
1 file changed, 147 insertions(+), 5 deletions(-)
diff --git a/includes/class-options.php b/includes/class-options.php
index f1853c0..e32a940 100644
--- a/includes/class-options.php
+++ b/includes/class-options.php
@@ -26,7 +26,7 @@ class DCWP_Options {
* @var string
* @since 0.2.1
*/
- protected $key = 'doubleclick_for_wordpress_doubleclick';
+ protected $key = 'doubleclick_for_wordpress';
/**
* Options page metabox ID.
@@ -34,7 +34,7 @@ class DCWP_Options {
* @var string
* @since 0.2.1
*/
- protected $metabox_id = 'doubleclick_for_wordpress_doubleclick_metabox';
+ protected $metabox_id = 'doubleclick_for_wordpress_metabox';
/**
* Options Page title.
@@ -63,7 +63,7 @@ public function __construct( $plugin ) {
$this->hooks();
// Set our title.
- $this->title = esc_attr__( 'DoubleClick for WordPress Doubleclick', 'doubleclick-for-wordpress' );
+ $this->title = esc_attr__( 'DoubleClick', 'doubleclick-for-wordpress' );
}
/**
@@ -76,7 +76,7 @@ public function hooks() {
// Hook in our actions to the admin.
add_action( 'admin_init', array( $this, 'admin_init' ) );
add_action( 'admin_menu', array( $this, 'add_options_page' ) );
-
+ add_action( 'admin_init', array( $this, 'register_options' ) );
}
/**
@@ -94,7 +94,8 @@ public function admin_init() {
* @since 0.2.1
*/
public function add_options_page() {
- $this->options_page = add_menu_page(
+ $this->options_page = add_submenu_page(
+ 'options-general.php',
$this->title,
$this->title,
'manage_options',
@@ -113,7 +114,148 @@ public function admin_page_display() {
?>