Packages
phx_new
1.4.0-dev.0
1.8.9
1.8.8
1.8.7
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.8.0-rc.4
1.8.0-rc.3
1.8.0-rc.2
1.8.0-rc.1
1.8.0-rc.0
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.7.0-rc.3
1.7.0-rc.2
1.7.0-rc.1
1.7.0-rc.0
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.15
1.5.14
1.5.13
1.5.12
1.5.11
1.5.10
1.5.9
1.5.8
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.0
1.4.18
1.4.17
1.4.16
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.3
1.4.0-rc.2
1.4.0-rc.1
1.4.0-rc.0
1.4.0-dev.0
1.3.5
Phoenix framework project generator. Provides a `mix phx.new` task to bootstrap a new Elixir application with Phoenix dependencies.
Current section
Files
Jump to
Current section
Files
templates/phx_assets/phoenix.js
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Phoenix=t():e.Phoenix=t()}(window,function(){return function(e){var t={};function s(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,s),i.l=!0,i.exports}return s.m=e,s.c=t,s.d=function(e,t,n){s.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},s.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},s.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return s.d(t,"a",t),t},s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},s.p="",s(s.s=2)}([function(e,t,s){"use strict";s.r(t),s.d(t,"Channel",function(){return d}),s.d(t,"Socket",function(){return g}),s.d(t,"LongPoll",function(){return v}),s.d(t,"Ajax",function(){return j}),s.d(t,"Presence",function(){return b});const n="undefined"!=typeof self?self:window,i="2.0.0",o={connecting:0,open:1,closing:2,closed:3},r=1e4,h=1e3,a={closed:"closed",errored:"errored",joined:"joined",joining:"joining",leaving:"leaving"},c={close:"phx_close",error:"phx_error",join:"phx_join",reply:"phx_reply",leave:"phx_leave"},l=[c.close,c.error,c.join,c.reply,c.leave],u={longpoll:"longpoll",websocket:"websocket"};let f=e=>{if("function"==typeof e)return e;return function(){return e}};class p{constructor(e,t,s,n){this.channel=e,this.event=t,this.payload=s||function(){return{}},this.receivedResp=null,this.timeout=n,this.timeoutTimer=null,this.recHooks=[],this.sent=!1}resend(e){this.timeout=e,this.reset(),this.send()}send(){this.hasReceived("timeout")||(this.startTimeout(),this.sent=!0,this.channel.socket.push({topic:this.channel.topic,event:this.event,payload:this.payload(),ref:this.ref,join_ref:this.channel.joinRef()}))}receive(e,t){return this.hasReceived(e)&&t(this.receivedResp.response),this.recHooks.push({status:e,callback:t}),this}reset(){this.cancelRefEvent(),this.ref=null,this.refEvent=null,this.receivedResp=null,this.sent=!1}matchReceive({status:e,response:t,ref:s}){this.recHooks.filter(t=>t.status===e).forEach(e=>e.callback(t))}cancelRefEvent(){this.refEvent&&this.channel.off(this.refEvent)}cancelTimeout(){clearTimeout(this.timeoutTimer),this.timeoutTimer=null}startTimeout(){this.timeoutTimer&&this.cancelTimeout(),this.ref=this.channel.socket.makeRef(),this.refEvent=this.channel.replyEventName(this.ref),this.channel.on(this.refEvent,e=>{this.cancelRefEvent(),this.cancelTimeout(),this.receivedResp=e,this.matchReceive(e)}),this.timeoutTimer=setTimeout(()=>{this.trigger("timeout",{})},this.timeout)}hasReceived(e){return this.receivedResp&&this.receivedResp.status===e}trigger(e,t){this.channel.trigger(this.refEvent,{status:e,response:t})}}class d{constructor(e,t,s){this.state=a.closed,this.topic=e,this.params=f(t||{}),this.socket=s,this.bindings=[],this.bindingRef=0,this.timeout=this.socket.timeout,this.joinedOnce=!1,this.joinPush=new p(this,c.join,this.params,this.timeout),this.pushBuffer=[],this.rejoinTimer=new y(()=>this.rejoinUntilConnected(),this.socket.reconnectAfterMs),this.joinPush.receive("ok",()=>{this.state=a.joined,this.rejoinTimer.reset(),this.pushBuffer.forEach(e=>e.send()),this.pushBuffer=[]}),this.onClose(()=>{this.rejoinTimer.reset(),this.socket.log("channel",`close ${this.topic} ${this.joinRef()}`),this.state=a.closed,this.socket.remove(this)}),this.onError(e=>{this.isLeaving()||this.isClosed()||(this.socket.log("channel",`error ${this.topic}`,e),this.state=a.errored,this.rejoinTimer.scheduleTimeout())}),this.joinPush.receive("timeout",()=>{if(!this.isJoining())return;this.socket.log("channel",`timeout ${this.topic} (${this.joinRef()})`,this.joinPush.timeout),new p(this,c.leave,f({}),this.timeout).send(),this.state=a.errored,this.joinPush.reset(),this.rejoinTimer.scheduleTimeout()}),this.on(c.reply,(e,t)=>{this.trigger(this.replyEventName(t),e)})}rejoinUntilConnected(){this.rejoinTimer.scheduleTimeout(),this.socket.isConnected()&&this.rejoin()}join(e=this.timeout){if(this.joinedOnce)throw"tried to join multiple times. 'join' can only be called a single time per channel instance";return this.joinedOnce=!0,this.rejoin(e),this.joinPush}onClose(e){this.on(c.close,e)}onError(e){return this.on(c.error,t=>e(t))}on(e,t){let s=this.bindingRef++;return this.bindings.push({event:e,ref:s,callback:t}),s}off(e,t){this.bindings=this.bindings.filter(s=>!(s.event===e&&(void 0===t||t===s.ref)))}canPush(){return this.socket.isConnected()&&this.isJoined()}push(e,t,s=this.timeout){if(!this.joinedOnce)throw`tried to push '${e}' to '${this.topic}' before joining. Use channel.join() before pushing events`;let n=new p(this,e,function(){return t},s);return this.canPush()?n.send():(n.startTimeout(),this.pushBuffer.push(n)),n}leave(e=this.timeout){this.state=a.leaving;let t=()=>{this.socket.log("channel",`leave ${this.topic}`),this.trigger(c.close,"leave")},s=new p(this,c.leave,f({}),e);return s.receive("ok",()=>t()).receive("timeout",()=>t()),s.send(),this.canPush()||s.trigger("ok",{}),s}onMessage(e,t,s){return t}isMember(e,t,s,n){if(this.topic!==e)return!1;let i=l.indexOf(t)>=0;return!n||!i||n===this.joinRef()||(this.socket.log("channel","dropping outdated message",{topic:e,event:t,payload:s,joinRef:n}),!1)}joinRef(){return this.joinPush.ref}sendJoin(e){this.state=a.joining,this.joinPush.resend(e)}rejoin(e=this.timeout){this.isLeaving()||this.sendJoin(e)}trigger(e,t,s,n){let i=this.onMessage(e,t,s,n);if(t&&!i)throw"channel onMessage callbacks must return the payload, modified or unmodified";this.bindings.filter(t=>t.event===e).map(e=>e.callback(i,s,n||this.joinRef()))}replyEventName(e){return`chan_reply_${e}`}isClosed(){return this.state===a.closed}isErrored(){return this.state===a.errored}isJoined(){return this.state===a.joined}isJoining(){return this.state===a.joining}isLeaving(){return this.state===a.leaving}}const m={encode(e,t){let s=[e.join_ref,e.ref,e.topic,e.event,e.payload];return t(JSON.stringify(s))},decode(e,t){let[s,n,i,o,r]=JSON.parse(e);return t({join_ref:s,ref:n,topic:i,event:o,payload:r})}};class g{constructor(e,t={}){this.stateChangeCallbacks={open:[],close:[],error:[],message:[]},this.channels=[],this.sendBuffer=[],this.ref=0,this.timeout=t.timeout||r,this.transport=t.transport||n.WebSocket||v,this.defaultEncoder=m.encode,this.defaultDecoder=m.decode,this.transport!==v?(this.encode=t.encode||this.defaultEncoder,this.decode=t.decode||this.defaultDecoder):(this.encode=this.defaultEncoder,this.decode=this.defaultDecoder),this.heartbeatIntervalMs=t.heartbeatIntervalMs||3e4,this.reconnectAfterMs=t.reconnectAfterMs||function(e){return[1e3,2e3,5e3,1e4][e-1]||1e4},this.logger=t.logger||function(){},this.longpollerTimeout=t.longpollerTimeout||2e4,this.params=f(t.params||{}),this.endPoint=`${e}/${u.websocket}`,this.heartbeatTimer=null,this.pendingHeartbeatRef=null,this.reconnectTimer=new y(()=>{this.teardown(()=>this.connect())},this.reconnectAfterMs)}protocol(){return location.protocol.match(/^https/)?"wss":"ws"}endPointURL(){let e=j.appendParams(j.appendParams(this.endPoint,this.params()),{vsn:i});return"/"!==e.charAt(0)?e:"/"===e.charAt(1)?`${this.protocol()}:${e}`:`${this.protocol()}://${location.host}${e}`}disconnect(e,t,s){this.reconnectTimer.reset(),this.teardown(e,t,s)}connect(e){e&&(console&&console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor"),this.params=f(e)),this.conn||(this.conn=new this.transport(this.endPointURL()),this.conn.timeout=this.longpollerTimeout,this.conn.onopen=(()=>this.onConnOpen()),this.conn.onerror=(e=>this.onConnError(e)),this.conn.onmessage=(e=>this.onConnMessage(e)),this.conn.onclose=(e=>this.onConnClose(e)))}log(e,t,s){this.logger(e,t,s)}onOpen(e){this.stateChangeCallbacks.open.push(e)}onClose(e){this.stateChangeCallbacks.close.push(e)}onError(e){this.stateChangeCallbacks.error.push(e)}onMessage(e){this.stateChangeCallbacks.message.push(e)}onConnOpen(){this.log("transport",`connected to ${this.endPointURL()}`),this.flushSendBuffer(),this.reconnectTimer.reset(),this.conn.skipHeartbeat||(clearInterval(this.heartbeatTimer),this.heartbeatTimer=setInterval(()=>this.sendHeartbeat(),this.heartbeatIntervalMs)),this.stateChangeCallbacks.open.forEach(e=>e())}teardown(e,t,s){this.conn&&(this.conn.onclose=function(){},t?this.conn.close(t,s||""):this.conn.close(),this.conn=null),e&&e()}onConnClose(e){this.log("transport","close",e),this.triggerChanError(),clearInterval(this.heartbeatTimer),e&&e.code!==h&&this.reconnectTimer.scheduleTimeout(),this.stateChangeCallbacks.close.forEach(t=>t(e))}onConnError(e){this.log("transport",e),this.triggerChanError(),this.stateChangeCallbacks.error.forEach(t=>t(e))}triggerChanError(){this.channels.forEach(e=>e.trigger(c.error))}connectionState(){switch(this.conn&&this.conn.readyState){case o.connecting:return"connecting";case o.open:return"open";case o.closing:return"closing";default:return"closed"}}isConnected(){return"open"===this.connectionState()}remove(e){this.channels=this.channels.filter(t=>t.joinRef()!==e.joinRef())}channel(e,t={}){let s=new d(e,t,this);return this.channels.push(s),s}push(e){let{topic:t,event:s,payload:n,ref:i,join_ref:o}=e,r=()=>{this.encode(e,e=>{this.conn.send(e)})};this.log("push",`${t} ${s} (${o}, ${i})`,n),this.isConnected()?r():this.sendBuffer.push(r)}makeRef(){let e=this.ref+1;return e===this.ref?this.ref=0:this.ref=e,this.ref.toString()}sendHeartbeat(){if(this.isConnected()){if(this.pendingHeartbeatRef)return this.pendingHeartbeatRef=null,this.log("transport","heartbeat timeout. Attempting to re-establish connection"),void this.conn.close(h,"hearbeat timeout");this.pendingHeartbeatRef=this.makeRef(),this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:this.pendingHeartbeatRef})}}flushSendBuffer(){this.isConnected()&&this.sendBuffer.length>0&&(this.sendBuffer.forEach(e=>e()),this.sendBuffer=[])}onConnMessage(e){this.decode(e.data,e=>{let{topic:t,event:s,payload:n,ref:i,join_ref:o}=e;i&&i===this.pendingHeartbeatRef&&(this.pendingHeartbeatRef=null),this.log("receive",`${n.status||""} ${t} ${s} ${i&&"("+i+")"||""}`,n),this.channels.filter(e=>e.isMember(t,s,n,o)).forEach(e=>e.trigger(s,n,i,o)),this.stateChangeCallbacks.message.forEach(t=>t(e))})}}class v{constructor(e){this.endPoint=null,this.token=null,this.skipHeartbeat=!0,this.onopen=function(){},this.onerror=function(){},this.onmessage=function(){},this.onclose=function(){},this.pollEndpoint=this.normalizeEndpoint(e),this.readyState=o.connecting,this.poll()}normalizeEndpoint(e){return e.replace("ws://","http://").replace("wss://","https://").replace(new RegExp("(.*)/"+u.websocket),"$1/"+u.longpoll)}endpointURL(){return j.appendParams(this.pollEndpoint,{token:this.token})}closeAndRetry(){this.close(),this.readyState=o.connecting}ontimeout(){this.onerror("timeout"),this.closeAndRetry()}poll(){this.readyState!==o.open&&this.readyState!==o.connecting||j.request("GET",this.endpointURL(),"application/json",null,this.timeout,this.ontimeout.bind(this),e=>{if(e){var{status:t,token:s,messages:n}=e;this.token=s}else var t=0;switch(t){case 200:n.forEach(e=>this.onmessage({data:e})),this.poll();break;case 204:this.poll();break;case 410:this.readyState=o.open,this.onopen(),this.poll();break;case 0:case 500:this.onerror(),this.closeAndRetry();break;default:throw`unhandled poll status ${t}`}})}send(e){j.request("POST",this.endpointURL(),"application/json",e,this.timeout,this.onerror.bind(this,"timeout"),e=>{e&&200===e.status||(this.onerror(e&&e.status),this.closeAndRetry())})}close(e,t){this.readyState=o.closed,this.onclose()}}class j{static request(e,t,s,i,o,r,h){if(n.XDomainRequest){let s=new XDomainRequest;this.xdomainRequest(s,e,t,i,o,r,h)}else{let a=n.XMLHttpRequest?new n.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");this.xhrRequest(a,e,t,s,i,o,r,h)}}static xdomainRequest(e,t,s,n,i,o,r){e.timeout=i,e.open(t,s),e.onload=(()=>{let t=this.parseJSON(e.responseText);r&&r(t)}),o&&(e.ontimeout=o),e.onprogress=(()=>{}),e.send(n)}static xhrRequest(e,t,s,n,i,o,r,h){e.open(t,s,!0),e.timeout=o,e.setRequestHeader("Content-Type",n),e.onerror=(()=>{h&&h(null)}),e.onreadystatechange=(()=>{if(e.readyState===this.states.complete&&h){let t=this.parseJSON(e.responseText);h(t)}}),r&&(e.ontimeout=r),e.send(i)}static parseJSON(e){if(!e||""===e)return null;try{return JSON.parse(e)}catch(t){return console&&console.log("failed to parse JSON response",e),null}}static serialize(e,t){let s=[];for(var n in e){if(!e.hasOwnProperty(n))continue;let i=t?`${t}[${n}]`:n,o=e[n];"object"==typeof o?s.push(this.serialize(o,i)):s.push(encodeURIComponent(i)+"="+encodeURIComponent(o))}return s.join("&")}static appendParams(e,t){if(0===Object.keys(t).length)return e;return`${e}${e.match(/\?/)?"&":"?"}${this.serialize(t)}`}}j.states={complete:4};class b{constructor(e,t={}){let s=t.events||{state:"presence_state",diff:"presence_diff"};this.state={},this.pendingDiffs=[],this.channel=e,this.joinRef=null,this.caller={onJoin:function(){},onLeave:function(){},onSync:function(){}},this.channel.on(s.state,e=>{let{onJoin:t,onLeave:s,onSync:n}=this.caller;this.joinRef=this.channel.joinRef(),this.state=b.syncState(this.state,e,t,s),this.pendingDiffs.forEach(e=>{this.state=b.syncDiff(this.state,e,t,s)}),this.pendingDiffs=[],n()}),this.channel.on(s.diff,e=>{let{onJoin:t,onLeave:s,onSync:n}=this.caller;this.inPendingSyncState()?this.pendingDiffs.push(e):(this.state=b.syncDiff(this.state,e,t,s),n())})}onJoin(e){this.caller.onJoin=e}onLeave(e){this.caller.onLeave=e}onSync(e){this.caller.onSync=e}list(e){return b.list(this.state,e)}inPendingSyncState(){return!this.joinRef||this.joinRef!==this.channel.joinRef()}static syncState(e,t,s,n){let i=this.clone(e),o={},r={};return this.map(i,(e,s)=>{t[e]||(r[e]=s)}),this.map(t,(e,t)=>{let s=i[e];if(s){let n=t.metas.map(e=>e.phx_ref),i=s.metas.map(e=>e.phx_ref),h=t.metas.filter(e=>i.indexOf(e.phx_ref)<0),a=s.metas.filter(e=>n.indexOf(e.phx_ref)<0);h.length>0&&(o[e]=t,o[e].metas=h),a.length>0&&(r[e]=this.clone(s),r[e].metas=a)}else o[e]=t}),this.syncDiff(i,{joins:o,leaves:r},s,n)}static syncDiff(e,{joins:t,leaves:s},n,i){let o=this.clone(e);return n||(n=function(){}),i||(i=function(){}),this.map(t,(e,t)=>{let s=o[e];if(o[e]=t,s){let t=o[e].metas.map(e=>e.phx_ref),n=s.metas.filter(e=>t.indexOf(e.phx_ref)<0);o[e].metas.unshift(...n)}n(e,s,t)}),this.map(s,(e,t)=>{let s=o[e];if(!s)return;let n=t.metas.map(e=>e.phx_ref);s.metas=s.metas.filter(e=>n.indexOf(e.phx_ref)<0),i(e,s,t),0===s.metas.length&&delete o[e]}),o}static list(e,t){return t||(t=function(e,t){return t}),this.map(e,(e,s)=>t(e,s))}static map(e,t){return Object.getOwnPropertyNames(e).map(s=>t(s,e[s]))}static clone(e){return JSON.parse(JSON.stringify(e))}}class y{constructor(e,t){this.callback=e,this.timerCalc=t,this.timer=null,this.tries=0}reset(){this.tries=0,clearTimeout(this.timer)}scheduleTimeout(){clearTimeout(this.timer),this.timer=setTimeout(()=>{this.tries=this.tries+1,this.callback()},this.timerCalc(this.tries+1))}}},function(e,t){var s;s=function(){return this}();try{s=s||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(s=window)}e.exports=s},function(e,t,s){"use strict";(function(t){e.exports=t.Phoenix=s(0)}).call(this,s(1))}])});