Merge branch 'master' into ja-review-panel

This commit is contained in:
James Allen 2016-10-18 16:52:41 +01:00
commit e717caab7f
20 changed files with 44479 additions and 82967 deletions

View file

@ -160,10 +160,10 @@ module.exports = (grunt) ->
paths:
"moment": "libs/#{PackageVersions.lib('moment')}"
"mathjax": "/js/libs/mathjax/MathJax.js?config=TeX-AMS_HTML"
"libs/pdf": "libs/#{PackageVersions.lib('pdfjs')}/pdf"
"pdfjs-dist/build/pdf": "libs/#{PackageVersions.lib('pdfjs')}/pdf"
"ace": "#{PackageVersions.lib('ace')}"
shim:
"libs/pdf":
"pdfjs-dist/build/pdf":
deps: ["libs/#{PackageVersions.lib('pdfjs')}/compatibility"]
skipDirOptimize: true
@ -173,7 +173,7 @@ module.exports = (grunt) ->
exclude: ["libs"]
}, {
name: "ide",
exclude: ["libs", "libs/pdf"]
exclude: ["libs", "pdfjs-dist/build/pdf"]
}, {
name: "libs"
},{

View file

@ -101,7 +101,7 @@ Thank you
#{settings.appName} - <%= siteUrl %>
"""
compiledTemplate: _.template """
<p>Hi, <%= owner.email %> wants to share <a href="<%= project.url %>">'<%= project.name %>'</a> with you</p>
<p>Hi, <%= owner.email %> wants to share <a href="<%= inviteUrl %>">'<%= project.name %>'</a> with you</p>
<center>
<a style="text-decoration: none; width: 200px; background-color: #a93629; border: 1px solid #e24b3b; border-radius: 3px; padding: 15px; margin: 24px; display: block;" href="<%= inviteUrl %>" style="text-decoration:none" target="_blank">
<span style= "font-size:16px;font-family:Helvetica,Arial;font-weight:400;color:#fff;white-space:nowrap;display:block; text-align:center">

View file

@ -52,6 +52,8 @@ module.exports =
text: options.text
replyTo: options.replyTo || Settings.email.replyToAddress
socketTimeout: 30 * 1000
if Settings.email.textEncoding?
opts.textEncoding = textEncoding
client.sendMail options, (err, res)->
if err?
logger.err err:err, "error sending message"

View file

@ -1,5 +1,5 @@
version = {
"pdfjs": "1.3.91p1"
"pdfjs": "1.6.210p1"
"moment": "2.9.0"
"ace": "1.2.5"
}

View file

@ -87,6 +87,10 @@ block content
block requirejs
script(type="text/javascript" src='/socket.io/socket.io.js')
//- don't use cdn for worker
- var pdfWorkerPath = buildJsPath('/libs/' + lib('pdfjs') + '/pdf.worker', {cdn:false,fingerprint:false})
//- We need to do .replace(/\//g, '\\/') do that '</script>' -> '<\/script>'
//- and doesn't prematurely end the script tag.
script(type='text/javascript').
@ -101,13 +105,14 @@ block requirejs
"paths" : {
"mathjax": "#{buildJsPath('/libs/mathjax/MathJax.js', {cdn:false, fingerprint:false, qs:{config:'TeX-AMS_HTML'}})}",
"moment": "libs/#{lib('moment')}",
"libs/pdf": "libs/#{lib('pdfjs')}/pdf",
"pdfjs-dist/build/pdf": "libs/#{lib('pdfjs')}/pdf",
"pdfjs-dist/build/pdf.worker": "#{pdfWorkerPath}",
"ace": "#{lib('ace')}"
},
"urlArgs" : "fingerprint=#{fingerprint(jsPath + 'ide.js')}-#{fingerprint(jsPath + 'libs.js')}",
"waitSeconds": 0,
"shim": {
"libs/pdf": {
"pdfjs-dist/build/pdf": {
"deps": ["libs/#{lib('pdfjs')}/compatibility"]
},
"ace/ext-searchbox": {
@ -125,13 +130,9 @@ block requirejs
};
window.aceFingerprint = "#{fingerprint(jsPath + lib('ace') + '/ace.js')}"
- var pdfPath = "libs/" + lib('pdfjs') + "/pdf.worker.js"
- var fingerprintedPath = fingerprint(jsPath+pdfPath)
- var pdfJsWorkerPath = buildJsPath(pdfPath, {cdn:false,qs:{fingerprint:fingerprintedPath}}) // don't use worker for cdn
- var aceWorkerPath = user.betaProgram ? buildJsPath(lib('ace'), {cdn:false,fingerprint:false}) : "" // don't use worker for cdn
- var aceWorkerPath = user.betaProgram ? buildJsPath(lib('ace'), {cdn:false,fingerprint:false}) : "" // don't use cdn for worker
script(type='text/javascript').
window.pdfJsWorkerPath = "#{pdfJsWorkerPath}";
window.aceWorkerPath = "#{aceWorkerPath}";
script(

View file

@ -229,7 +229,7 @@ div.full-size.pdf(ng-controller="PdfController")
p.entry-content(ng-show="entry.content") {{ entry.content.trim() }}
p
div
.files-dropdown-container
a.btn.btn-default.btn-sm(
href,
@ -344,7 +344,7 @@ div.full-size.pdf(ng-controller="PdfController")
strong #{translate("ask_proj_owner_to_upgrade_for_faster_compiles")}
p #{translate("free_accounts_have_timeout_upgrade_to_increase")}
p Plus:
p
div
ul.list-unstyled
li
i.fa.fa-check &nbsp;

View file

@ -47,130 +47,8 @@ block content
div(ng-if="normalPrice")
span.small Normally {{price.currency.symbol}}{{normalPrice}}
.row
div(sixpack-switch="subscription-form")
.col-md-12(sixpack-default)
form(ng-show="planName",novalidate)
.row
.col-md-12
.form-group
.row
.col-md-6
label.radio-inline
input.paymentTypeOption(type="radio",value="credit_card", ng-model="paymentMethod.value")
i.fa.fa-cc-mastercard.fa-3x
span &nbsp;
i.fa.fa-cc-visa.fa-3x
.col-md-6
label.radio-inline
input.paymentTypeOption(type="radio", value="paypal", ng-model="paymentMethod.value")
i.fa.fa-cc-paypal.fa-3x
.alert.alert-warning.small(ng-show="genericError")
strong {{genericError}}
span(ng-hide="paymentMethod.value == 'paypal'")
.row
.col-md-12
.form-group
div.alert.alert-warning.small(ng-hide="validation.correctCvv") #{translate("invalid")} CVV
div.alert.alert-warning.small(ng-hide="validation.correctCardNumber") #{translate("invalid")} #{translate("credit_card_number")}
.row
.col-md-6
.form-group(ng-class="validation.number == false || validation.errorFields.number ? 'has-error' : ''")
input.form-control(ng-model='data.number', ng-blur="validateCardNumber()", placeholder="#{translate('credit_card_number')}")
.col-md-3
.form-group(ng-class="validation.correctCvv == false || validation.errorFields.cvv ? 'has-error' : ''")
input.form-control(ng-model='data.cvv', ng-blur="validateCvv()", placeholder="CVV")
.row
.col-md-12
div.alert.alert-warning.small(ng-hide="validation.correctExpiry") #{translate("invalid")} #{translate("expiry")}
.row
.col-md-3
.form-group(ng-class="validation.correctExpiry == false || validation.errorFields.month ? 'has-error' : ''")
select.form-control(data-recurly='month', ng-change="validateExpiry()", ng-model='data.month')
option(value="", disabled, selected) Month
option(value="01") 01
option(value="02") 02
option(value="03") 03
option(value="04") 04
option(value="05") 05
option(value="06") 06
option(value="07") 07
option(value="08") 08
option(value="09") 09
option(value="10") 10
option(value="11") 11
option(value="12") 12
.col-md-4
.form-group(ng-class="validation.correctExpiry == false || validation.errorFields.year ? 'has-error' : ''")
select.form-control(data-recurly='year', ng-change="validateExpiry()", ng-model='data.year')
option(value="", disabled, selected) Year
option(value="2016") 2016
option(value="2017") 2017
option(value="2018") 2018
option(value="2019") 2019
option(value="2020") 2020
option(value="2021") 2021
option(value="2022") 2022
option(value="2023") 2023
option(value="2024") 2024
option(value="2025") 2025
option(value="2026") 2026
.row
.col-md-6
.form-group(ng-class="validation.errorFields.first_name ? 'has-error' : ''")
input.form-control(type='text', value='', maxlength='255', , onkeyup='', data-recurly="first_name", ng-model="data.first_name", required, placeholder="#{translate('first_name')}")
.col-md-6
.form-group(ng-class="validation.errorFields.last_name ? 'has-error' : ''")
input.form-control(type='text', value='', maxlength='255', onkeyup='', data-recurly="last_name", ng-model="data.last_name", required, placeholder="#{translate('last_name')}")
hr
.row
.col-md-12
.form-group(ng-class="validation.errorFields.address1 ? 'has-error' : ''")
label #{translate("billing_address")}
input.form-control(type='text', value='', maxlength='255', onkeyup='', ng-model="data.address1", placeholder="#{translate('address')}")
.form-group(ng-class="validation.errorFields.address2 ? 'has-error' : ''")
input.form-control(type='text', value='', maxlength='255', onkeyup='', ng-model="data.address2", placeholder="#{translate('address')}")
.form-group(ng-class="validation.errorFields.state ? 'has-error' : ''")
input.form-control(type='text', value='', maxlength='255', onkeyup='', ng-model="data.state", placeholder="#{translate('state')}")
.row
.col-md-7
.form-group(ng-class="validation.errorFields.city ? 'has-error' : ''")
input.form-control(type='text', value='', maxlength='255', onkeyup='', data-recurly="city", ng-model="data.city", placeholder="#{translate('city')}")
.col-md-5(ng-class="validation.errorFields.postal_code ? 'has-error' : ''")
input.form-control(type='text', value='', maxlength='255', onkeyup='', data-recurly="postal_code", ng-model="data.postal_code", placeholder="#{translate('zip_post_code')}")
.row
.col-md-7
.form-group(ng-class="validation.errorFields.country ? 'has-error' : ''")
select.form-control(data-recurly="country", ng-model="data.country", ng-change="updateCountry()", required)
mixin countries_options()
.row
.col-md-8
if (showCouponField)
.form-group
input.form-control(type='text', ng-blur="applyCoupon()", ng-model="data.coupon", placeholder="#{translate('coupon')}")
.row
.col-md-8
if (showVatField)
.form-group
input.form-control(type='text', ng-blur="applyVatNumber()", ng-model="data.vat_number", placeholder="#{translate('vat_number')}")
.row
.col-xs-7
.form-group
button.btn.btn-success(ng-click="submit()", ng-disabled="processing", sixpack-convert="payment-left-menu-bottom") #{translate("upgrade_now")}
.col-xs-3.pricingBreakdown
div(ng-if="price.next.subtotal != price.next.total") Subtotal
div(ng-if="price.next.tax!='0.00'") Tax
div
strong Total
.col-xs-2
div(ng-if="price.next.subtotal != price.next.total").pull-right {{price.currency.symbol}}{{price.next.subtotal}}
div(ng-if="price.next.tax!='0.00'").pull-right {{price.currency.symbol}}{{price.next.tax}}
div.pull-right
strong {{price.currency.symbol}}{{price.next.total}}
.col-md-12(sixpack-when="simple")
div()
.col-md-12()
form(
ng-if="planName"
name="simpleCCForm"
@ -321,7 +199,6 @@ block content
button.btn.btn-success.btn-block(
ng-click="submit()"
ng-disabled="processing || !isFormValid(simpleCCForm);"
sixpack-convert="payment-left-menu-bottom"
)
span(ng-show="processing")
i.fa.fa-spinner.fa-spin

View file

@ -166,6 +166,8 @@ module.exports = settings =
price: 0
features: defaultFeatures
}]
enableSubscriptions:false
# i18n
# ------

View file

@ -231,6 +231,12 @@ define [
_aceDeltaToSimpleDelta: (aceDelta, docLines) ->
start = aceDelta.start
if !start?
error = new Error("aceDelta had no start event.")
Raven?.captureException(error, {
aceDelta: JSON.stringify(aceDelta)
})
throw error
linesBefore = docLines.slice(0, start.row)
position =
linesBefore.join("").length + # full lines

View file

@ -6,9 +6,6 @@ define [
pdfViewer
) ->
if PDFJS?
PDFJS.workerSrc = window.pdfJsWorkerPath
App.directive "pdfng", ["$timeout", "localStorage", ($timeout, localStorage) ->
return {
scope: {

View file

@ -1,26 +1,46 @@
define [
"base"
], (App) ->
"pdfjs-dist/build/pdf"
], (App, PDFJS) ->
# App = angular.module 'PDFRenderer', ['pdfAnnotations', 'pdfTextLayer']
App.factory 'PDFRenderer', ['$q', '$timeout', 'pdfAnnotations', 'pdfTextLayer', 'pdfSpinner', ($q, $timeout, pdfAnnotations, pdfTextLayer, pdfSpinner) ->
# Have a single worker used by all rendering, to avoid reloading
RenderThread = { worker: null, count: 0}
getRenderThread = () ->
if RenderThread.count > 16 # recycle the worker periodically to avoid leaks
RenderThread.readyToDestroy = true
RenderThread = { worker: null, count: 0 }
RenderThread.worker ||= new PDFJS.PDFWorker('pdfjsworker')
RenderThread.count++
return RenderThread
resetWorker = (thread) ->
thread.worker.destroy() if thread.readyToDestroy
# The PDF page renderer
class PDFRenderer
JOB_QUEUE_INTERVAL: 25
PAGE_LOAD_TIMEOUT: 60*1000
INDICATOR_DELAY1: 100 # time to delay before showing the indicator
INDICATOR_DELAY2: 250 # time until the indicator starts animating
TEXTLAYER_TIMEOUT: 100
constructor: (@url, @options) ->
if navigator.userAgent?.indexOf("Edge/") >= 0 or navigator.userAgent?.indexOf("rv:11.0") >= 0 # IE 11
# Microsoft Edge does not work well with font-face (Sept 2016)
PDFJS.disableFontFace = true
if window.location?.search?.indexOf("disable-font-face=true") >= 0
window.PDFJS.disableFontFace = true
else
window.PDFJS.disableFontFace = false
if @options.disableAutoFetch
PDFJS.disableAutoFetch = true # prevent loading whole file
window.PDFJS.disableAutoFetch = true # prevent loading whole file
# PDFJS.disableStream
# PDFJS.disableRange
@scale = @options.scale || 1
@pdfjs = PDFJS.getDocument {url: @url, rangeChunkSize: 2*65536}
@thread = getRenderThread()
@pdfjs = PDFJS.getDocument {url: @url, rangeChunkSize: 2*65536, worker: @thread.worker}
@pdfjs.onProgress = @options.progressCallback
@document = $q.when(@pdfjs)
@navigateFn = @options.navigateFn
@ -245,6 +265,12 @@ define [
return
canvas = $('<canvas class="pdf-canvas pdfng-rendering"></canvas>')
# In Windows+IE we must have the canvas in the DOM during
# rendering to see the fonts defined in the DOM. If we try to
# render 'offscreen' then all the text will be sans-serif.
# Previously we rendered offscreen and added in the canvas
# when rendering was complete.
element.canvas.replaceWith(canvas)
viewport = page.getViewport (scale)
@ -282,6 +308,7 @@ define [
textLayer = new pdfTextLayer({
textLayerDiv: element.text[0]
viewport: viewport
renderer: PDFJS.renderTextLayer
})
annotationsLayer = new pdfAnnotations({
@ -296,12 +323,14 @@ define [
transform: [pixelRatio, 0, 0, pixelRatio, 0, 0]
}
textLayerTimeout = @TEXTLAYER_TIMEOUT
result.then () ->
# page render success
element.canvas.replaceWith(canvas)
canvas.removeClass('pdfng-rendering')
page.getTextContent().then (textContent) ->
page.getTextContent({normalizeWhitespace: true}).then (textContent) ->
textLayer.setTextContent textContent
textLayer.render(textLayerTimeout)
, (error) ->
self.errorCallback?(error)
page.getAnnotations().then (annotations) ->
@ -320,8 +349,9 @@ define [
destroy: () ->
@shuttingDown = true
@resetState()
@pdfjs.then (document) ->
@pdfjs.then (document) =>
document.cleanup()
document.destroy()
resetWorker(@thread)
]

View file

@ -1,225 +1,57 @@
define [
"base"
], (App) ->
# App = angular.module 'pdfTextLayer', []
# uses the PDFJS text layer renderer to provide invisible overlayed
# text for searching
App.factory 'pdfTextLayer', [ () ->
# TRANSLATED FROM pdf.js-1.0.712
# pdf.js-1.0.712/web/ui_utils.js
# pdf.js-1.0.712/web/text_layer_builder.js
# -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
# Copyright 2012 Mozilla Foundation
# *
# * Licensed under the Apache License, Version 2.0 (the "License");
# * you may not use this file except in compliance with the License.
# * You may obtain a copy of the License at
# *
# * http://www.apache.org/licenses/LICENSE-2.0
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
#
# globals CustomStyle, scrollIntoView, PDFJS
# ms
# optimised CSS custom property getter/setter
CustomStyle = (CustomStyleClosure = ->
# As noted on: http://www.zachstronaut.com/posts/2009/02/17/
# animate-css-transforms-firefox-webkit.html
# in some versions of IE9 it is critical that ms appear in this list
# before Moz
CustomStyle = ->
prefixes = [
'ms'
'Moz'
'Webkit'
'O'
]
_cache = {}
CustomStyle.getProp = get = (propName, element) ->
# check cache only when no element is given
return _cache[propName] if arguments.length is 1 and typeof _cache[propName] is 'string'
element = element or document.documentElement
style = element.style
prefixed = undefined
uPropName = undefined
# test standard property first
return (_cache[propName] = propName) if typeof style[propName] is 'string'
# capitalize
uPropName = propName.charAt(0).toUpperCase() + propName.slice(1)
# test vendor specific properties
i = 0
l = prefixes.length
while i < l
prefixed = prefixes[i] + uPropName
return (_cache[propName] = prefixed) if typeof style[prefixed] is 'string'
i++
#if all fails then set to undefined
_cache[propName] = 'undefined'
CustomStyle.setProp = set = (propName, element, str) ->
prop = @getProp(propName)
element.style[prop] = str if prop isnt 'undefined'
return
CustomStyle
)()
#################################
isAllWhitespace = (str) ->
not NonWhitespaceRegexp.test(str)
'use strict'
FIND_SCROLL_OFFSET_TOP = -50
FIND_SCROLL_OFFSET_LEFT = -400
MAX_TEXT_DIVS_TO_RENDER = 100000
RENDER_DELAY = 200
NonWhitespaceRegexp = /\S/
###*
TextLayerBuilder provides text-selection functionality for the PDF.
It does this by creating overlay divs over the PDF text. These divs
contain text that matches the PDF text they are overlaying. This object
also provides a way to highlight text that is being searched for.
###
class pdfTextLayer
constructor: (options) ->
@textLayerDiv = options.textLayerDiv
@layoutDone = false
@divContentDone = false
@pageIdx = options.pageIndex
@matches = []
@lastScrollSource = options.lastScrollSource or null
@viewport = options.viewport
@isViewerInPresentationMode = options.isViewerInPresentationMode
@textDivs = []
@findController = options.findController or null
@renderer = options.renderer
@renderingDone = false
renderLayer: () ->
render: (timeout) ->
if @renderingDone or not @divContentDone
return
if @textLayerRenderTask?
@textLayerRenderTask.cancel()
@textLayerRenderTask = null
@textDivs = []
textLayerFrag = document.createDocumentFragment()
textDivs = @textDivs
textDivsLength = textDivs.length
canvas = document.createElement('canvas')
ctx = canvas.getContext('2d')
# No point in rendering many divs as it would make the browser
# unusable even after the divs are rendered.
return if textDivsLength > MAX_TEXT_DIVS_TO_RENDER
lastFontSize = undefined
lastFontFamily = undefined
i = 0
while i < textDivsLength
textDiv = textDivs[i]
if textDiv.dataset.isWhitespace
i++
continue
fontSize = textDiv.style.fontSize
fontFamily = textDiv.style.fontFamily
@textLayerRenderTask = @renderer {
textContent: this.textContent,
container: textLayerFrag,
viewport: this.viewport,
textDivs: this.textDivs,
timeout: timeout,
enhanceTextSelection: this.enhanceTextSelection,
}
# Only build font string and set to context if different from last.
if fontSize isnt lastFontSize or fontFamily isnt lastFontFamily
ctx.font = fontSize + ' ' + fontFamily
lastFontSize = fontSize
lastFontFamily = fontFamily
width = ctx.measureText(textDiv.textContent).width
if width > 0
textLayerFrag.appendChild textDiv
textLayerSuccess = () =>
@textLayerDiv.appendChild(textLayerFrag)
@renderingDone = true
if textDiv.dataset.canvasWidth?
# Dataset values come of type string.
textScale = textDiv.dataset.canvasWidth / width;
transform = 'scaleX(' + textScale + ')'
else
transform = ''
rotation = textDiv.dataset.angle
if rotation
transform = 'rotate(' + rotation + 'deg) ' + transform
if transform
CustomStyle.setProp 'transform', textDiv, transform
i++
@textLayerDiv.appendChild textLayerFrag
return
textLayerFailure = () ->
return # canceled or failed to render text layer -- skipping errors
appendText: (geom, styles) ->
style = styles[geom.fontName]
textDiv = document.createElement('div')
@textDivs.push textDiv
if isAllWhitespace(geom.str)
textDiv.dataset.isWhitespace = true
return
tx = PDFJS.Util.transform(@viewport.transform, geom.transform)
angle = Math.atan2(tx[1], tx[0])
angle += Math.PI / 2 if style.vertical
fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3]))
fontAscent = fontHeight
if style.ascent
fontAscent = style.ascent * fontAscent
else fontAscent = (1 + style.descent) * fontAscent if style.descent
left = undefined
top = undefined
if angle is 0
left = tx[4]
top = tx[5] - fontAscent
else
left = tx[4] + (fontAscent * Math.sin(angle))
top = tx[5] - (fontAscent * Math.cos(angle))
textDiv.style.left = left + 'px'
textDiv.style.top = top + 'px'
textDiv.style.fontSize = fontHeight + 'px'
textDiv.style.fontFamily = style.fontFamily
textDiv.textContent = geom.str
textDiv.ondblclick = (e) ->
if (window.getSelection)
window.getSelection().removeAllRanges();
else if (document.selection)
document.selection.empty();
# |fontName| is only used by the Font Inspector. This test will succeed
# when e.g. the Font Inspector is off but the Stepper is on, but it's
# not worth the effort to do a more accurate test.
textDiv.dataset.fontName = geom.fontName if PDFJS.pdfBug
# Storing into dataset will convert number into string.
textDiv.dataset.angle = angle * (180 / Math.PI) if angle isnt 0
# We don't bother scaling single-char text divs, because it has very
# little effect on text highlighting. This makes scrolling on docs with
# lots of such divs a lot faster.
if textDiv.textContent.length > 1
if style.vertical
textDiv.dataset.canvasWidth = geom.height * @viewport.scale
else
textDiv.dataset.canvasWidth = geom.width * @viewport.scale
return
@textLayerRenderTask.promise.then(textLayerSuccess, textLayerFailure)
setTextContent: (textContent) ->
@textContent = textContent
textItems = textContent.items
i = 0
len = textItems.length
if (@textLayerRenderTask)
@textLayerRenderTask.cancel();
@textLayerRenderTask = null;
while i < len
@appendText textItems[i], textContent.styles
i++
@divContentDone = true
@renderLayer()
return
@textContent = textContent;
@divContentDone = true;
]

View file

@ -6,7 +6,6 @@ define [
"ide/pdfng/directives/pdfRenderer"
"ide/pdfng/directives/pdfPage"
"ide/pdfng/directives/pdfSpinner"
"libs/pdf"
], (
App
pdfTextLayer

View file

@ -157,13 +157,11 @@ define [
isPaypal : postData.subscriptionDetails.isPaypal
}
sixpack.convert "subscription-form"
$http.post("/user/subscription/create", postData)
.success (data, status, headers)->
sixpack.convert "in-editor-free-trial-plan", pricing.items.plan.code, (err)->
event_tracking.sendMB "subscription-submission-success"
window.location.href = "/user/subscription/thank-you"
event_tracking.sendMB "subscription-submission-success"
window.location.href = "/user/subscription/thank-you"
.error (data, status, headers)->
$scope.processing = false
$scope.genericError = "Something went wrong processing the request"

View file

@ -1,563 +0,0 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals VBArray, PDFJS */
'use strict';
// Initializing PDFJS global object here, it case if we need to change/disable
// some PDF.js features, e.g. range requests
if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
// Checking if the typed arrays are supported
// Support: iOS<6.0 (subarray), IE<10, Android<4.0
(function checkTypedArrayCompatibility() {
if (typeof Uint8Array !== 'undefined') {
// Support: iOS<6.0
if (typeof Uint8Array.prototype.subarray === 'undefined') {
Uint8Array.prototype.subarray = function subarray(start, end) {
return new Uint8Array(this.slice(start, end));
};
Float32Array.prototype.subarray = function subarray(start, end) {
return new Float32Array(this.slice(start, end));
};
}
// Support: Android<4.1
if (typeof Float64Array === 'undefined') {
window.Float64Array = Float32Array;
}
return;
}
function subarray(start, end) {
return new TypedArray(this.slice(start, end));
}
function setArrayOffset(array, offset) {
if (arguments.length < 2) {
offset = 0;
}
for (var i = 0, n = array.length; i < n; ++i, ++offset) {
this[offset] = array[i] & 0xFF;
}
}
function TypedArray(arg1) {
var result, i, n;
if (typeof arg1 === 'number') {
result = [];
for (i = 0; i < arg1; ++i) {
result[i] = 0;
}
} else if ('slice' in arg1) {
result = arg1.slice(0);
} else {
result = [];
for (i = 0, n = arg1.length; i < n; ++i) {
result[i] = arg1[i];
}
}
result.subarray = subarray;
result.buffer = result;
result.byteLength = result.length;
result.set = setArrayOffset;
if (typeof arg1 === 'object' && arg1.buffer) {
result.buffer = arg1.buffer;
}
return result;
}
window.Uint8Array = TypedArray;
window.Int8Array = TypedArray;
// we don't need support for set, byteLength for 32-bit array
// so we can use the TypedArray as well
window.Uint32Array = TypedArray;
window.Int32Array = TypedArray;
window.Uint16Array = TypedArray;
window.Float32Array = TypedArray;
window.Float64Array = TypedArray;
})();
// URL = URL || webkitURL
// Support: Safari<7, Android 4.2+
(function normalizeURLObject() {
if (!window.URL) {
window.URL = window.webkitURL;
}
})();
// Object.defineProperty()?
// Support: Android<4.0, Safari<5.1
(function checkObjectDefinePropertyCompatibility() {
if (typeof Object.defineProperty !== 'undefined') {
var definePropertyPossible = true;
try {
// some browsers (e.g. safari) cannot use defineProperty() on DOM objects
// and thus the native version is not sufficient
Object.defineProperty(new Image(), 'id', { value: 'test' });
// ... another test for android gb browser for non-DOM objects
var Test = function Test() {};
Test.prototype = { get id() { } };
Object.defineProperty(new Test(), 'id',
{ value: '', configurable: true, enumerable: true, writable: false });
} catch (e) {
definePropertyPossible = false;
}
if (definePropertyPossible) {
return;
}
}
Object.defineProperty = function objectDefineProperty(obj, name, def) {
delete obj[name];
if ('get' in def) {
obj.__defineGetter__(name, def['get']);
}
if ('set' in def) {
obj.__defineSetter__(name, def['set']);
}
if ('value' in def) {
obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
this.__defineGetter__(name, function objectDefinePropertyGetter() {
return value;
});
return value;
});
obj[name] = def.value;
}
};
})();
// No XMLHttpRequest#response?
// Support: IE<11, Android <4.0
(function checkXMLHttpRequestResponseCompatibility() {
var xhrPrototype = XMLHttpRequest.prototype;
var xhr = new XMLHttpRequest();
if (!('overrideMimeType' in xhr)) {
// IE10 might have response, but not overrideMimeType
// Support: IE10
Object.defineProperty(xhrPrototype, 'overrideMimeType', {
value: function xmlHttpRequestOverrideMimeType(mimeType) {}
});
}
if ('responseType' in xhr) {
return;
}
// The worker will be using XHR, so we can save time and disable worker.
PDFJS.disableWorker = true;
// Support: IE9
if (typeof VBArray !== 'undefined') {
Object.defineProperty(xhrPrototype, 'response', {
get: function xmlHttpRequestResponseGet() {
if (this.responseType === 'arraybuffer') {
return new Uint8Array(new VBArray(this.responseBody).toArray());
} else {
return this.responseText;
}
}
});
return;
}
// other browsers
function responseTypeSetter() {
// will be only called to set "arraybuffer"
this.overrideMimeType('text/plain; charset=x-user-defined');
}
if (typeof xhr.overrideMimeType === 'function') {
Object.defineProperty(xhrPrototype, 'responseType',
{ set: responseTypeSetter });
}
function responseGetter() {
var text = this.responseText;
var i, n = text.length;
var result = new Uint8Array(n);
for (i = 0; i < n; ++i) {
result[i] = text.charCodeAt(i) & 0xFF;
}
return result.buffer;
}
Object.defineProperty(xhrPrototype, 'response', { get: responseGetter });
})();
// window.btoa (base64 encode function) ?
// Support: IE<10
(function checkWindowBtoaCompatibility() {
if ('btoa' in window) {
return;
}
var digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
window.btoa = function windowBtoa(chars) {
var buffer = '';
var i, n;
for (i = 0, n = chars.length; i < n; i += 3) {
var b1 = chars.charCodeAt(i) & 0xFF;
var b2 = chars.charCodeAt(i + 1) & 0xFF;
var b3 = chars.charCodeAt(i + 2) & 0xFF;
var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
buffer += (digits.charAt(d1) + digits.charAt(d2) +
digits.charAt(d3) + digits.charAt(d4));
}
return buffer;
};
})();
// window.atob (base64 encode function)?
// Support: IE<10
(function checkWindowAtobCompatibility() {
if ('atob' in window) {
return;
}
// https://github.com/davidchambers/Base64.js
var digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
window.atob = function (input) {
input = input.replace(/=+$/, '');
if (input.length % 4 === 1) {
throw new Error('bad atob input');
}
for (
// initialize result and counters
var bc = 0, bs, buffer, idx = 0, output = '';
// get next character
buffer = input.charAt(idx++);
// character found in table?
// initialize bit storage and add its ascii value
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
// and if not first of each 4 characters,
// convert the first 8 bits to one ascii character
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
) {
// try to find character in table (0-63, not found => -1)
buffer = digits.indexOf(buffer);
}
return output;
};
})();
// Function.prototype.bind?
// Support: Android<4.0, iOS<6.0
(function checkFunctionPrototypeBindCompatibility() {
if (typeof Function.prototype.bind !== 'undefined') {
return;
}
Function.prototype.bind = function functionPrototypeBind(obj) {
var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
var bound = function functionPrototypeBindBound() {
var args = headArgs.concat(Array.prototype.slice.call(arguments));
return fn.apply(obj, args);
};
return bound;
};
})();
// HTMLElement dataset property
// Support: IE<11, Safari<5.1, Android<4.0
(function checkDatasetProperty() {
var div = document.createElement('div');
if ('dataset' in div) {
return; // dataset property exists
}
Object.defineProperty(HTMLElement.prototype, 'dataset', {
get: function() {
if (this._dataset) {
return this._dataset;
}
var dataset = {};
for (var j = 0, jj = this.attributes.length; j < jj; j++) {
var attribute = this.attributes[j];
if (attribute.name.substring(0, 5) !== 'data-') {
continue;
}
var key = attribute.name.substring(5).replace(/\-([a-z])/g,
function(all, ch) {
return ch.toUpperCase();
});
dataset[key] = attribute.value;
}
Object.defineProperty(this, '_dataset', {
value: dataset,
writable: false,
enumerable: false
});
return dataset;
},
enumerable: true
});
})();
// HTMLElement classList property
// Support: IE<10, Android<4.0, iOS<5.0
(function checkClassListProperty() {
var div = document.createElement('div');
if ('classList' in div) {
return; // classList property exists
}
function changeList(element, itemName, add, remove) {
var s = element.className || '';
var list = s.split(/\s+/g);
if (list[0] === '') {
list.shift();
}
var index = list.indexOf(itemName);
if (index < 0 && add) {
list.push(itemName);
}
if (index >= 0 && remove) {
list.splice(index, 1);
}
element.className = list.join(' ');
return (index >= 0);
}
var classListPrototype = {
add: function(name) {
changeList(this.element, name, true, false);
},
contains: function(name) {
return changeList(this.element, name, false, false);
},
remove: function(name) {
changeList(this.element, name, false, true);
},
toggle: function(name) {
changeList(this.element, name, true, true);
}
};
Object.defineProperty(HTMLElement.prototype, 'classList', {
get: function() {
if (this._classList) {
return this._classList;
}
var classList = Object.create(classListPrototype, {
element: {
value: this,
writable: false,
enumerable: true
}
});
Object.defineProperty(this, '_classList', {
value: classList,
writable: false,
enumerable: false
});
return classList;
},
enumerable: true
});
})();
// Check console compatibility
// In older IE versions the console object is not available
// unless console is open.
// Support: IE<10
(function checkConsoleCompatibility() {
if (!('console' in window)) {
window.console = {
log: function() {},
error: function() {},
warn: function() {}
};
} else if (!('bind' in console.log)) {
// native functions in IE9 might not have bind
console.log = (function(fn) {
return function(msg) { return fn(msg); };
})(console.log);
console.error = (function(fn) {
return function(msg) { return fn(msg); };
})(console.error);
console.warn = (function(fn) {
return function(msg) { return fn(msg); };
})(console.warn);
}
})();
// Check onclick compatibility in Opera
// Support: Opera<15
(function checkOnClickCompatibility() {
// workaround for reported Opera bug DSK-354448:
// onclick fires on disabled buttons with opaque content
function ignoreIfTargetDisabled(event) {
if (isDisabled(event.target)) {
event.stopPropagation();
}
}
function isDisabled(node) {
return node.disabled || (node.parentNode && isDisabled(node.parentNode));
}
if (navigator.userAgent.indexOf('Opera') !== -1) {
// use browser detection since we cannot feature-check this bug
document.addEventListener('click', ignoreIfTargetDisabled, true);
}
})();
// Checks if possible to use URL.createObjectURL()
// Support: IE
(function checkOnBlobSupport() {
// sometimes IE loosing the data created with createObjectURL(), see #3977
if (navigator.userAgent.indexOf('Trident') >= 0) {
PDFJS.disableCreateObjectURL = true;
}
})();
// Checks if navigator.language is supported
(function checkNavigatorLanguage() {
if ('language' in navigator &&
/^[a-z]+(-[A-Z]+)?$/.test(navigator.language)) {
return;
}
function formatLocale(locale) {
var split = locale.split(/[-_]/);
split[0] = split[0].toLowerCase();
if (split.length > 1) {
split[1] = split[1].toUpperCase();
}
return split.join('-');
}
var language = navigator.language || navigator.userLanguage || 'en-US';
PDFJS.locale = formatLocale(language);
})();
(function checkRangeRequests() {
// Safari has issues with cached range requests see:
// https://github.com/mozilla/pdf.js/issues/3260
// Last tested with version 6.0.4.
// Support: Safari 6.0+
var isSafari = Object.prototype.toString.call(
window.HTMLElement).indexOf('Constructor') > 0;
// Older versions of Android (pre 3.0) has issues with range requests, see:
// https://github.com/mozilla/pdf.js/issues/3381.
// Make sure that we only match webkit-based Android browsers,
// since Firefox/Fennec works as expected.
// Support: Android<3.0
var regex = /Android\s[0-2][^\d]/;
var isOldAndroid = regex.test(navigator.userAgent);
if (isSafari || isOldAndroid) {
PDFJS.disableRange = true;
}
})();
// Check if the browser supports manipulation of the history.
// Support: IE<10, Android<4.2
(function checkHistoryManipulation() {
// Android 2.x has so buggy pushState support that it was removed in
// Android 3.0 and restored as late as in Android 4.2.
// Support: Android 2.x
if (!history.pushState || navigator.userAgent.indexOf('Android 2.') >= 0) {
PDFJS.disableHistory = true;
}
})();
// Support: IE<11, Chrome<21, Android<4.4, Safari<6
(function checkSetPresenceInImageData() {
// IE < 11 will use window.CanvasPixelArray which lacks set function.
if (window.CanvasPixelArray) {
if (typeof window.CanvasPixelArray.prototype.set !== 'function') {
window.CanvasPixelArray.prototype.set = function(arr) {
for (var i = 0, ii = this.length; i < ii; i++) {
this[i] = arr[i];
}
};
}
} else {
// Old Chrome and Android use an inaccessible CanvasPixelArray prototype.
// Because we cannot feature detect it, we rely on user agent parsing.
var polyfill = false, versionMatch;
if (navigator.userAgent.indexOf('Chrom') >= 0) {
versionMatch = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
// Chrome < 21 lacks the set function.
polyfill = versionMatch && parseInt(versionMatch[2]) < 21;
} else if (navigator.userAgent.indexOf('Android') >= 0) {
// Android < 4.4 lacks the set function.
// Android >= 4.4 will contain Chrome in the user agent,
// thus pass the Chrome check above and not reach this block.
polyfill = /Android\s[0-4][^\d]/g.test(navigator.userAgent);
} else if (navigator.userAgent.indexOf('Safari') >= 0) {
versionMatch = navigator.userAgent.
match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//);
// Safari < 6 lacks the set function.
polyfill = versionMatch && parseInt(versionMatch[1]) < 6;
}
if (polyfill) {
var contextPrototype = window.CanvasRenderingContext2D.prototype;
contextPrototype._createImageData = contextPrototype.createImageData;
contextPrototype.createImageData = function(w, h) {
var imageData = this._createImageData(w, h);
imageData.data.set = function(arr) {
for (var i = 0, ii = this.length; i < ii; i++) {
this[i] = arr[i];
}
};
return imageData;
};
}
}
})();
// Support: IE<10, Android<4.0, iOS
(function checkRequestAnimationFrame() {
function fakeRequestAnimationFrame(callback) {
window.setTimeout(callback, 20);
}
var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
if (isIOS) {
// requestAnimationFrame on iOS is broken, replacing with fake one.
window.requestAnimationFrame = fakeRequestAnimationFrame;
return;
}
if ('requestAnimationFrame' in window) {
return;
}
window.requestAnimationFrame =
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
fakeRequestAnimationFrame;
})();
(function checkCanvasSizeLimitation() {
var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
var isAndroid = /Android/g.test(navigator.userAgent);
if (isIOS || isAndroid) {
// 5MP
PDFJS.maxCanvasPixels = 5242880;
}
})();

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,3 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +14,8 @@
*/
/* globals VBArray, PDFJS */
'use strict';
(function compatibilityWrapper() {
'use strict';
// Initializing PDFJS global object here, it case if we need to change/disable
// some PDF.js features, e.g. range requests
@ -447,20 +446,10 @@ if (typeof PDFJS === 'undefined') {
// Checks if navigator.language is supported
(function checkNavigatorLanguage() {
if ('language' in navigator &&
/^[a-z]+(-[A-Z]+)?$/.test(navigator.language)) {
if ('language' in navigator) {
return;
}
function formatLocale(locale) {
var split = locale.split(/[-_]/);
split[0] = split[0].toLowerCase();
if (split.length > 1) {
split[1] = split[1].toUpperCase();
}
return split.join('-');
}
var language = navigator.language || navigator.userLanguage || 'en-US';
PDFJS.locale = formatLocale(language);
PDFJS.locale = navigator.userLanguage || 'en-US';
})();
(function checkRangeRequests() {
@ -479,7 +468,10 @@ if (typeof PDFJS === 'undefined') {
var regex = /Android\s[0-2][^\d]/;
var isOldAndroid = regex.test(navigator.userAgent);
if (isSafari || isOldAndroid) {
// Range requests are broken in Chrome 39 and 40, https://crbug.com/442318
var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent);
if (isSafari || isOldAndroid || isChromeWithRangeBug) {
PDFJS.disableRange = true;
PDFJS.disableStream = true;
}
@ -529,9 +521,9 @@ if (typeof PDFJS === 'undefined') {
if (polyfill) {
var contextPrototype = window.CanvasRenderingContext2D.prototype;
contextPrototype._createImageData = contextPrototype.createImageData;
var createImageData = contextPrototype.createImageData;
contextPrototype.createImageData = function(w, h) {
var imageData = this._createImageData(w, h);
var imageData = createImageData.call(this, w, h);
imageData.data.set = function(arr) {
for (var i = 0, ii = this.length; i < ii; i++) {
this[i] = arr[i];
@ -539,6 +531,8 @@ if (typeof PDFJS === 'undefined') {
};
return imageData;
};
// this closure will be kept referenced, so clear its vars
contextPrototype = null;
}
}
})();
@ -572,3 +566,31 @@ if (typeof PDFJS === 'undefined') {
PDFJS.maxCanvasPixels = 5242880;
}
})();
// Disable fullscreen support for certain problematic configurations.
// Support: IE11+ (when embedded).
(function checkFullscreenSupport() {
var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 &&
window.parent !== window);
if (isEmbeddedIE) {
PDFJS.disableFullscreen = true;
}
})();
// Provides document.currentScript support
// Support: IE, Chrome<29.
(function checkCurrentScript() {
if ('currentScript' in document) {
return;
}
Object.defineProperty(document, 'currentScript', {
get: function () {
var scripts = document.getElementsByTagName('script');
return scripts[scripts.length - 1];
},
enumerable: true,
configurable: true
});
})();
}).call((typeof window === 'undefined') ? this : window);