Repository: amark/gun Branch: master Commit: ed27b48569ef Files: 571 Total size: 3.6 MB Directory structure: gitextract_sxejevxy/ ├── .dockerignore ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ └── ci.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .travis.yml ├── CHANGELOG.md ├── Dockerfile ├── LICENSE.md ├── Procfile ├── README.md ├── RELEASE.md ├── SECURITY.md ├── app.json ├── as.js ├── axe.js ├── bower.json ├── browser.js ├── examples/ │ ├── .gitignore │ ├── Main.js │ ├── angular/ │ │ ├── .angular-cli.json │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── README.md │ │ ├── e2e/ │ │ │ ├── app.e2e-spec.ts │ │ │ ├── app.po.ts │ │ │ └── tsconfig.e2e.json │ │ ├── example_package.json │ │ ├── karma.conf.js │ │ ├── protractor.conf.js │ │ ├── server.js │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── app.component.css │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.spec.ts │ │ │ │ ├── app.component.ts │ │ │ │ ├── app.module.ts │ │ │ │ ├── gun.helper.ts │ │ │ │ └── gun.service.ts │ │ │ ├── assets/ │ │ │ │ └── .gitkeep │ │ │ ├── environments/ │ │ │ │ ├── environment.prod.ts │ │ │ │ └── environment.ts │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ ├── polyfills.ts │ │ │ ├── styles.css │ │ │ ├── test.ts │ │ │ ├── tsconfig.app.json │ │ │ ├── tsconfig.spec.json │ │ │ └── typings.d.ts │ │ ├── tsconfig.json │ │ └── tslint.json │ ├── axe.html │ ├── basic/ │ │ ├── chat.html │ │ ├── emoji.html │ │ ├── meet.html │ │ ├── note.html │ │ ├── paste.html │ │ ├── poll.html │ │ ├── post.html │ │ ├── private.html │ │ ├── schedule.html │ │ ├── screen.html │ │ ├── stream.html │ │ ├── tables.html │ │ ├── upload.html │ │ ├── user.html │ │ └── video.html │ ├── chat/ │ │ ├── index.html │ │ └── user.html │ ├── contact/ │ │ └── index.html │ ├── docs.html │ ├── express.js │ ├── game/ │ │ ├── furball.html │ │ ├── nts.html │ │ ├── space.html │ │ └── win.html │ ├── hapi.js │ ├── http.js │ ├── https.sh │ ├── index.html │ ├── infinite-scroll/ │ │ ├── ScrollWindow.js │ │ ├── index.html │ │ ├── index.js │ │ └── style.css │ ├── install.sh │ ├── jquery.js │ ├── json/ │ │ └── index.html │ ├── move/ │ │ └── index.html │ ├── party.html │ ├── react/ │ │ ├── README.md │ │ ├── public/ │ │ │ └── index.html │ │ ├── src/ │ │ │ ├── App.js │ │ │ ├── App.test.js │ │ │ ├── Chat.js │ │ │ ├── Json.js │ │ │ ├── Todos.js │ │ │ ├── index.css │ │ │ ├── index.js │ │ │ └── style.css │ │ └── todo.html │ ├── react-native/ │ │ ├── .babelrc │ │ ├── .buckconfig │ │ ├── .flowconfig │ │ ├── .gitattributes │ │ ├── .gitignore │ │ ├── .watchmanconfig │ │ ├── README.md │ │ ├── android/ │ │ │ ├── app/ │ │ │ │ ├── BUCK │ │ │ │ ├── build.gradle │ │ │ │ ├── proguard-rules.pro │ │ │ │ └── src/ │ │ │ │ └── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── assets/ │ │ │ │ │ └── html/ │ │ │ │ │ └── blank.html │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── gundemo/ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ │ └── res/ │ │ │ │ └── values/ │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ ├── build.gradle │ │ │ ├── gradle/ │ │ │ │ └── wrapper/ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradle.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ ├── keystores/ │ │ │ │ ├── BUCK │ │ │ │ └── debug.keystore.properties │ │ │ └── settings.gradle │ │ ├── app.json │ │ ├── index.js │ │ ├── ios/ │ │ │ ├── GunDemo/ │ │ │ │ ├── AppDelegate.h │ │ │ │ ├── AppDelegate.m │ │ │ │ ├── Base.lproj/ │ │ │ │ │ └── LaunchScreen.xib │ │ │ │ ├── Images.xcassets/ │ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ │ ├── Info.plist │ │ │ │ └── main.m │ │ │ ├── GunDemo-tvOS/ │ │ │ │ └── Info.plist │ │ │ ├── GunDemo-tvOSTests/ │ │ │ │ └── Info.plist │ │ │ ├── GunDemo.xcodeproj/ │ │ │ │ └── project.pbxproj │ │ │ └── GunDemoTests/ │ │ │ ├── GunDemoTests.m │ │ │ └── Info.plist │ │ ├── package.json │ │ ├── shim.js │ │ └── src/ │ │ ├── App/ │ │ │ ├── Demo.js │ │ │ ├── PolyFillCrypto.js │ │ │ ├── app.js │ │ │ └── index.js │ │ ├── extensions/ │ │ │ ├── asyncStorageAdapter.js │ │ │ └── sea.js │ │ └── webview-crypto/ │ │ ├── MainWorker.d.ts │ │ ├── MainWorker.js │ │ ├── WebViewWorker.d.ts │ │ ├── WebViewWorker.js │ │ ├── asyncSerialize.d.ts │ │ ├── asyncSerialize.js │ │ ├── compat.d.ts │ │ ├── compat.js │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── serializeBinary.d.ts │ │ ├── serializeBinary.js │ │ ├── webViewWorkerString.d.ts │ │ └── webViewWorkerString.js │ ├── relay-sqlite-example/ │ │ ├── README.md │ │ ├── capacitor.config.ts │ │ ├── index.html │ │ ├── package.json │ │ ├── src/ │ │ │ ├── App.vue │ │ │ ├── components/ │ │ │ │ └── RelayMode.vue │ │ │ ├── composables/ │ │ │ │ ├── GunStorageAdapter.ts │ │ │ │ ├── useNetwork.ts │ │ │ │ ├── useNetworkStatus.ts │ │ │ │ └── useToast.ts │ │ │ ├── main.ts │ │ │ ├── pages/ │ │ │ │ └── index.vue │ │ │ ├── router/ │ │ │ │ └── index.ts │ │ │ ├── services/ │ │ │ │ ├── dbVersionService.ts │ │ │ │ ├── globalServices.ts │ │ │ │ ├── initializeAppService.ts │ │ │ │ ├── sqliteService.ts │ │ │ │ └── storageService.ts │ │ │ └── theme/ │ │ │ └── variables.css │ │ ├── tsconfig.json │ │ ├── tsconfig.node.json │ │ └── vite.config.ts │ ├── relay.service │ ├── smoothie.js │ ├── start.js.html │ ├── stats.html │ ├── style.css │ ├── todo/ │ │ └── index.html │ ├── vanilla/ │ │ ├── screen.html │ │ ├── todo.html │ │ ├── user.html │ │ └── video.html │ ├── vue/ │ │ ├── index.html │ │ └── todo.html │ ├── wave.html │ ├── webpack/ │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src/ │ │ │ ├── app.js │ │ │ └── index.html │ │ └── webpack.config.js │ └── where/ │ └── index.html ├── gun.d.ts ├── gun.js ├── hooks/ │ ├── build │ └── post_push ├── index.d.ts ├── index.js ├── kit/ │ ├── web.css │ └── web.js ├── lib/ │ ├── afore.js │ ├── aws.js │ ├── axe.js │ ├── book.js │ ├── bye.js │ ├── crashed.js │ ├── cryptomodules.js │ ├── debug.js │ ├── dom.js │ ├── email.js │ ├── erase.js │ ├── evict.js │ ├── file.js │ ├── forget.js │ ├── fork.js │ ├── fsrm.js │ ├── fun.js │ ├── hot.js │ ├── http.js │ ├── hub.js │ ├── ipfs.js │ ├── ison.js │ ├── jsonp.js │ ├── later.d.ts │ ├── later.js │ ├── les.js │ ├── level.js │ ├── lex.js │ ├── list.js │ ├── load.d.ts │ ├── load.js │ ├── match.js │ ├── memdisk.js │ ├── meta.js │ ├── mix.js │ ├── mobile.js │ ├── monotype.js │ ├── multicast.js │ ├── nomem.js │ ├── normalize.js │ ├── not.d.ts │ ├── not.js │ ├── open.d.ts │ ├── open.js │ ├── path.d.ts │ ├── path.js │ ├── promise.d.ts │ ├── promise.js │ ├── radisk.d.ts │ ├── radisk.js │ ├── radisk2.js │ ├── radix.d.ts │ ├── radix.js │ ├── radix2.js │ ├── radmigtmp.js │ ├── ras.js │ ├── reboot.js │ ├── rfs.js │ ├── rfsmix.js │ ├── rindexed.d.ts │ ├── rindexed.js │ ├── rls.js │ ├── rmem.js │ ├── role.js │ ├── rs3.js │ ├── serve.js │ ├── server.js │ ├── service.js │ ├── shim.js │ ├── space.js │ ├── stats.js │ ├── store.d.ts │ ├── store.js │ ├── super.js │ ├── text-encoding/ │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── index.js │ │ ├── lib/ │ │ │ ├── encoding-indexes.js │ │ │ └── encoding.js │ │ └── package.json │ ├── then.d.ts │ ├── then.js │ ├── time.js │ ├── unbuild.js │ ├── unset.d.ts │ ├── unset.js │ ├── untitled.js │ ├── upload.js │ ├── utils.js │ ├── uws.js │ ├── verify.js │ ├── wave.js │ ├── webrtc.d.ts │ ├── webrtc.js │ ├── wire.js │ ├── ws.js │ ├── wsp.js │ ├── wsproto.js │ └── yson.js ├── nts.js ├── package.json ├── rad.js ├── sea/ │ ├── aeskey.js │ ├── array.js │ ├── auth.js │ ├── base64.js │ ├── buffer.js │ ├── certify.js │ ├── create.js │ ├── decrypt.js │ ├── encrypt.js │ ├── https.js │ ├── index.js │ ├── pair.js │ ├── recall.js │ ├── root.js │ ├── sea.js │ ├── secret.js │ ├── settings.js │ ├── sha1.js │ ├── sha256.js │ ├── share.js │ ├── shim.js │ ├── sign.js │ ├── then.js │ ├── user.js │ ├── verify.js │ └── work.js ├── sea.d.ts ├── sea.js ├── src/ │ ├── ask.js │ ├── back.js │ ├── book.js │ ├── chain.js │ ├── core.js │ ├── dup.js │ ├── get.js │ ├── index.js │ ├── localStorage.js │ ├── map.js │ ├── mesh.js │ ├── on.js │ ├── onto.js │ ├── polyfill/ │ │ └── unbuild.js │ ├── put.js │ ├── root.js │ ├── set.js │ ├── shim.js │ ├── state.js │ ├── valid.js │ └── websocket.js ├── test/ │ ├── abc.js │ ├── bug/ │ │ ├── 121.js │ │ ├── 1243.js │ │ ├── 322.js │ │ ├── 686.js │ │ └── 783.js │ ├── common.js │ ├── debug/ │ │ └── deep-set.html │ ├── download-log.html │ ├── expect.js │ ├── gun.html │ ├── https/ │ │ ├── ca.crt │ │ ├── ca.csr │ │ ├── ca.key │ │ ├── server.crt │ │ ├── server.csr │ │ ├── server.key │ │ ├── server.key.passphrase │ │ └── test.js │ ├── hub/ │ │ ├── .hubignore │ │ ├── hub-test.js │ │ ├── index.html │ │ └── whatever/ │ │ └── aws-key.txt │ ├── index.js │ ├── json2.js │ ├── mocha.css │ ├── mocha.html │ ├── mocha.js │ ├── normalize/ │ │ └── normalize.html │ ├── old/ │ │ ├── all.js │ │ ├── interface.js │ │ ├── performance.js │ │ ├── s3pricing.html │ │ ├── server.js │ │ ├── set.js │ │ ├── shoot.html │ │ ├── shoot.js │ │ ├── shotgun.js │ │ ├── timelines.txt │ │ └── tmp.js │ ├── panic/ │ │ ├── 1putackget.js │ │ ├── 2getget.js │ │ ├── 3puts.js │ │ ├── 4putackdedup.js │ │ ├── axe/ │ │ │ ├── 1no_self.js │ │ │ ├── 2no_dup.js │ │ │ ├── 3get_turns.js │ │ │ ├── 4get_subs.js │ │ │ ├── 5mob.js │ │ │ ├── index.html │ │ │ └── load_balance.js │ │ ├── b2s2s2b.js │ │ ├── bulkimport.js │ │ ├── chat-user.js │ │ ├── chat.js │ │ ├── curl-server.js │ │ ├── e2e/ │ │ │ ├── distributed.js │ │ │ ├── holy/ │ │ │ │ ├── grail.js │ │ │ │ ├── gun-server.js │ │ │ │ ├── index.html │ │ │ │ └── ports.json │ │ │ └── package.json │ │ ├── holy-grail.js │ │ ├── index.html │ │ ├── infinite-scroll/ │ │ │ ├── index.html │ │ │ └── index.js │ │ ├── large-nodes.js │ │ ├── latency.js │ │ ├── level.js │ │ ├── lexical.js │ │ ├── livestream.js │ │ ├── load.js │ │ ├── no-override.js │ │ ├── on-recovery.js │ │ ├── radisk.js │ │ ├── radisk_split_failure.js │ │ ├── s2s-all-delayed-peer-add.js │ │ ├── s2s-all.js │ │ ├── scale.js │ │ ├── set.js │ │ ├── shocknet.js │ │ ├── speak.js │ │ ├── thread.js │ │ ├── user-paste.js │ │ ├── users.js │ │ ├── util/ │ │ │ ├── load-browser-scripts.js │ │ │ └── open.js │ │ └── who.js │ ├── panic.html │ ├── ptsd/ │ │ ├── benchmark.js │ │ ├── memdisk.html │ │ ├── memdisk.js │ │ ├── memory.html │ │ ├── perf.js │ │ ├── ptsd.html │ │ ├── ptsd.js │ │ ├── radix.html │ │ ├── radix.js │ │ ├── spam.js │ │ ├── stool.css │ │ └── streampipe.js │ ├── rad/ │ │ ├── 2020and2021.js │ │ ├── bench.js │ │ ├── book.html │ │ ├── book.js │ │ ├── browser.html │ │ ├── crash.js │ │ ├── mocha.html │ │ ├── old2020json/ │ │ │ ├── ! │ │ │ └── %1C │ │ ├── parse.rad │ │ ├── rad.book.spec.js │ │ ├── rad.js │ │ └── recover.js │ ├── radix.js │ ├── sea/ │ │ ├── nodeauth.js │ │ ├── sea-tmp.html │ │ ├── sea.html │ │ ├── sea.js │ │ └── sea_old.js │ ├── server/ │ │ ├── http.js │ │ ├── node-client.js │ │ └── node-write.js │ ├── tmp/ │ │ ├── bigsync.js │ │ ├── contact.html │ │ ├── contacts.html │ │ ├── indexedDB.html │ │ ├── mitra/ │ │ │ ├── client_to_server.js │ │ │ └── gun_https2.js │ │ ├── radisk.html │ │ ├── say.html │ │ ├── seanode.js │ │ ├── space.html │ │ ├── time.html │ │ └── tmp.html │ ├── trace.html │ ├── trace.js │ └── wire.txt ├── tsconfig.json └── types/ ├── gun/ │ ├── GunCallbackGet.d.ts │ ├── GunCallbackMap.d.ts │ ├── GunCallbackOn.d.ts │ ├── GunCallbackOnce.d.ts │ ├── GunCallbackPut.d.ts │ ├── GunDataNode.d.ts │ ├── GunHookCallbackBye.d.ts │ ├── GunHookCallbackCreate.d.ts │ ├── GunHookCallbackGet.d.ts │ ├── GunHookCallbackHi.d.ts │ ├── GunHookCallbackIn.d.ts │ ├── GunHookCallbackOpt.d.ts │ ├── GunHookCallbackOut.d.ts │ ├── GunHookCallbackPut.d.ts │ ├── GunNodeGet.d.ts │ ├── GunNodePut.d.ts │ ├── GunOptions.d.ts │ ├── GunOptionsOn.d.ts │ ├── GunOptionsOnce.d.ts │ ├── GunOptionsPut.d.ts │ ├── GunPeer.d.ts │ ├── GunSchema.d.ts │ ├── GunSoul.d.ts │ ├── GunValueSimple.d.ts │ ├── IGun.d.ts │ ├── IGunChain.d.ts │ ├── IGunHookContext.d.ts │ ├── IGunInstance.d.ts │ ├── IGunInstanceHookHandler.d.ts │ ├── IGunInstanceRoot.d.ts │ ├── IGunMeta.d.ts │ ├── IGunOnEvent.d.ts │ ├── LEX.d.ts │ ├── LEXQuery.d.ts │ ├── _GunRoot.d.ts │ ├── index.d.ts │ └── pany.d.ts ├── index.d.ts ├── sea/ │ ├── GunCallbackUserAuth.d.ts │ ├── GunCallbackUserCreate.d.ts │ ├── GunHookCallbackAuth.d.ts │ ├── GunUser.d.ts │ ├── IGun.d.ts │ ├── IGunInstance.d.ts │ ├── IGunInstanceHookHandler.d.ts │ ├── IGunInstanceRoot.d.ts │ ├── IGunUserInstance.d.ts │ ├── IPolicy.d.ts │ ├── ISEA.d.ts │ ├── ISEAPair.d.ts │ ├── OptionsUserAuth.d.ts │ ├── OptionsUserRecall.d.ts │ ├── Policy.d.ts │ └── index.d.ts ├── test/ │ ├── gun-back.test-d.ts │ ├── gun-get.test-d.ts │ ├── gun-instance.test-d.ts │ ├── gun-map.test-d.ts │ ├── gun-on.test-d.ts │ ├── gun-once.test-d.ts │ ├── gun-opt.test-d.ts │ ├── gun-put.test-d.ts │ ├── gun-set.test-d.ts │ ├── gun-user-auth.test-d.ts │ ├── gun-user-leave.test-d.ts │ ├── gun-user-recall.test-d.ts │ ├── gun-user.test-d.ts │ ├── sea-certify.test-d.ts │ └── sea.test-d.ts └── utils.d.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dockerignore ================================================ node_modules radata stats.radata .git .gitignore *.md ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: amark patreon: gunDB open_collective: gun ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .github/workflows/ci.yml ================================================ name: ci on: push: pull_request: jobs: test: strategy: matrix: node-version: [14.x] os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: # checkout the code - name: Checkout uses: actions/checkout@v4 # Updated to v4 (latest as of 2025) # verify the version in package.json matches the release tag - name: Version uses: tcurdt/action-verify-version-npm@master # No version update as it's using @master # setup the node version - name: Setup Node ${{ matrix.node-version }} uses: actions/setup-node@v4 # Updated to v4 (latest as of 2025) with: node-version: ${{ matrix.node-version }} # cache node_modules if we can - name: Cache id: cache-modules uses: actions/cache@v4 # Updated to v4 (latest as of 2025) with: path: node_modules key: ${{ matrix.node-version }}-${{ runner.os }}-build-${{ hashFiles('package.json') }} # otherwise run install - name: Install if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install # run tests - name: Test run: npm test # create github release release: if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') needs: [test] runs-on: ubuntu-latest steps: # create github release (which triggers the release workflows) - name: Release uses: softprops/action-gh-release@v2 # Updated to v2 (latest stable version as of 2025) # env: # GITHUB_TOKEN: ${{ secrets.PAT }} # # publish latest master or release to dockerhub # dockerhub: # if: github.event_name == 'push' # needs: [test] # runs-on: ubuntu-latest # env: # image: ${{ secrets.DOCKERHUB_USERNAME }}/gun # steps: # # - name: Checkout # uses: actions/checkout@v4 # Updated to v4 # # - name: Login # env: # DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} # DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} # run: echo -n ${{ secrets.DOCKERHUB_TOKEN }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin # # - name: Build # run: | # echo "SHA=$GITHUB_SHA" # docker build --build-arg SHA=$GITHUB_SHA \ # BUILD_DATE=$(date +'%Y-%m-%dT%H:%M:%S') \ # VCS_REF=${GITHUB_REF} \ # VCS_URL=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} \ # VERSION=${GITHUB_REF##*/} \ # SHA=$GITHUB_SHA \ # --label "SHA=$GITHUB_SHA" \ # --tag ${{ env.image }}:${GITHUB_REF##*/} \ # --tag ${{ env.image }}:latest \ # . # # - name: Push # run: docker push ${{ env.image }} # publish release to npm npm: if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') needs: [test] runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 # Updated to v4 - name: Publish env: NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} run: | npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN npm install npm publish --access=public ================================================ FILE: .gitignore ================================================ node_modules npm-debug.log yarn.lock *data.json *data* *.db .idea/ *.bak *.new *.log v8.json *.DS_store isolate*.log .esm-cache .sessionStorage .localStorage /types/**/*.ts !/types/**/*.d.ts !/types/**/*.test-d.ts /gun.ts /temp/ ================================================ FILE: .npmignore ================================================ *.ts /temp/ !*.d.ts *.radata isolate-* ================================================ FILE: .prettierignore ================================================ * ================================================ FILE: .travis.yml ================================================ language: node_js branches: except: - debug - manhattan node_js: - 10 cache: directories: - node_modules ================================================ FILE: CHANGELOG.md ================================================ # CHANGELOG ## 0.2020.x `>0.2020.520` may break in-process `gun1` `gun2` message passing. Check `test/common.js` "Check multi instance message passing" for a hint and/or complain on community chat. - No breaking changes to core API. - Storage adapter `put` event breaking change (temporary?), RAD is official now and storage adapters should be RAD plugins instead of GUN adapters. - GUN soul format changed from being a random UUID to being a more predictable graph path (of where initially created) to support even better offline behavior. This means `null`ing & replacing an object will not create a new but re-merge. - Pretty much all internal GUN utility will be deleted, these are mostly undocumented but will affect some people - they will still be available as a separate file but deprecated. - As the DHT gets implemented, your relay peers may automatically connect to it, so do not assume your peer is standalone. `Gun({axe: false` should help prevent this but loses you most scaling properties. - The 2019 -> 2020 "changes" are happening gradually, based on experimental in-production tests. - As always, **most important** is to ask in the [community chat](http://chat.gun.eco) if you have any issues, and to keep up to date with changes. ## 0.2019.x Some RAD & SEA data format changes, but with as much backward compatibility as possible, tho ideally should be dropped. ## 0.9.x No breaking changes, but the new Radix Storage Engine (RSE) has been finally integrated and works with S3 as a backup. // Edit: commentary removed. ## 0.8.x Adapter interfaces have changed from `Gun.on('event', cb)` to `gun.on('event', cb)`, this will force adapters to be instance specific. `.path()` and `.not()` have been officially removed from the core bundle, you can bundle them yourself at `lib/path.js` and `lib/not.js` if you still need them. ## 0.7.x Small breaking change to `.val(cb)`: Previously `.val(cb)` would ONLY be called when data exists, like `.on(cb)`. However, due to popular demand, people wanted `.val(cb)` to also get called for `.not(cb)` rather than (before) it would "wait" until data arrived. NOTE: For dynamic paths, `.val(cb)` will still wait, like: `gun.get('users').map().val(cb)` because the behavior of the `map()` is simply to not fire anything down the chain unless items are found. ## 0.6.x Introduced experimental features, chaining `.val()` (no callback) and `.map(cb)` behaving as a map/reduce function. It also upgraded the socket adapters and did end-to-end load testing and correctness testing. ## 0.5.9 GUN 0.3 -> 0.4 -> 0.5 Migration Guide: `gun.back` -> `gun.back()`; `gun.get(key, cb)` -> cb(err, data) -> cb(at) at.err, at.put; `gun.map(cb)` -> `gun.map().on(cb)`; `gun.init` -> deprecated; `gun.put(data, cb)` -> cb(err, ok) -> cb(ack) ack.err, ack.ok; `gun.get(key)` global/absolute -> `gun.back(-1).get(key)`; `gun.key(key)` -> temporarily broken; ## 0.3.7 - Catch localStorage errors. ## 0.3.6 - Fixed S3 typo. ## 0.3.5 - Fixed server push. ## 0.3.4 - Breaking Change! `list.set(item)` returns the item's chain now, not the list chain. - Client and Server GUN servers are now more up to spec, trimmed excess HTTP/REST header data. - Gun.is.lex added. ## 0.3.3 - You can now link nodes natively, `gun.get('mark').path('owner').put(gun.get('cat'))`! - Sets (or tables, collections, lists) are now easily done with `gun.get('users').set(gun.get('person/mark'))`. ## 0.3.2 Bug fixes. ## 0.3.1 Bug fixes. ## 0.3 Migration Guide! Migrate by changing `.attach(` to `.wsp(` on your server if you have one with gun. Remove `.set()` (delete it), and change `.set($DATA)` (where you call set with something) to `.path('I' + Date.now() + 'R' + Gun.text.random(5)).put($DATA)`. If you have NodeJS style callbacks in your `.get` (which documentation previously recommended that you shouldn't) they previous took `err, graph` and now they take `err, node` (which means now using callback style is fine to use). Inside of `.not()` no longer use `return` or `this`, instead (probably) use `gun` and no `return`. If you are a module developer, use `opt.wire` now instead of `opt.hooks` and message Mark since he needs to talk to you since the wire protocol has changed. - Server side default `.wsp()` renamed from `.attach()`. - `.set()` deprecated because it did a bunch of random inconsistent things. Its useful behavior has now become implicit (see below) or can be done explicitly. - `.not()` it was previously common to `return` the chain inside of .not, beware that if you have code like `gun.get(key).not(function(){ return this.put({}).key(key) }).val()` cause `.val()` to be triggered twice (this is intentional, because it funnels two separate chains together) which previously didn't happen. To fix this, just don't return the chain. - `.put()` and `.path()` do implicit `.init()` by default, turn on explicit behavior with `Gun({init: true})`. - `.get(soul, cb)` cb is called back with `err, node` rather than `err, graph`. - Options `opt.wire` renamed from `opt.hooks`. - `.val()` when called empty automatically cleanly logs for convenience purposes. - `.init()` added. - `Gun.is.val` renamed from `Gun.is.value`. - `Gun.is.rel` renamed from `Gun.is.soul`. - `Gun.is.node.soul` renamed from `Gun.is.soul.on`. - `Gun.union.ify` renamed from `Gun.union.pseudo`. - `Gun.union.HAM` renamed from `Gun.HAM`. - `Gun.HAM` is now the actual HAM function for conflict resolution. - `Gun._.state` renamed from `Gun._.HAM`. - Maximum Callstack Exceeded is less problematic now, unless you intentionally choke the thread. #95 - Putting a regex or Date or NaN is actually detected and causes an error now while before it was silent. #122 #123 - `.on()` gets called when a key is later newly made while before it did not. #116 - `.val()` should not ever get called with a relation alone (internals should resolve it), this is fixed. #132 ================================================ FILE: Dockerfile ================================================ # install packages FROM node:lts-alpine as builder RUN mkdir /work WORKDIR /work RUN apk add --no-cache alpine-sdk python3 COPY package*.json ./ RUN mkdir -p node_modules RUN npm ci --only=production # fresh image without dev packages FROM node:lts-alpine # build-time metadata as defined at http://label-schema.org ARG BUILD_DATE ARG VCS_REF ARG VCS_URL ARG VERSION LABEL org.label-schema.build-date=$BUILD_DATE \ org.label-schema.name="Gun - Offline First, Javascript Graph Database" \ org.label-schema.url="http://gun.js.org" \ org.label-schema.vcs-ref=$VCS_REF \ org.label-schema.vcs-url=$VCS_URL \ org.label-schema.vendor="The Gun Database Team" \ org.label-schema.version=$VERSION \ org.label-schema.schema-version="1.0" ARG SHA RUN mkdir /work WORKDIR /work COPY --from=builder /work/node_modules ./node_modules RUN npm rebuild -q ADD . . RUN echo "{ \"sha\": \"$SHA\" }" > version.json RUN cat version.json EXPOSE 8080 EXPOSE 8765 CMD ["npm","start"] ================================================ FILE: LICENSE.md ================================================ Copyright (c) 2015 Mark Nadal 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. --- Copyright (c) 2015 Mark Nadal This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgement in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. --- Copyright 2015 Mark Nadal 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. ================================================ FILE: Procfile ================================================ web: node --inspect examples/http.js ================================================ FILE: README.md ================================================

[![](https://data.jsdelivr.com/v1/package/npm/gun/badge)](https://www.jsdelivr.com/package/npm/gun) ![Build](https://github.com/amark/gun/actions/workflows/ci.yml/badge.svg) [![Gitter](https://img.shields.io/gitter/room/amark/gun.js.svg)](http://chat.gun.eco) **GUN** is an [ecosystem](https://gun.eco/docs/Ecosystem) of **tools** that let you build [community run](https://www.nbcnews.com/tech/tech-news/these-technologists-think-internet-broken-so-they-re-building-another-n1030136) and [encrypted applications](https://gun.eco/docs/Cartoon-Cryptography) - like an Open Source Firebase or a Decentralized Dropbox. The [Internet Archive](https://news.ycombinator.com/item?id=17685682) and [100s of other apps](https://github.com/amark/gun/wiki/awesome-gun) run GUN in-production. + Multiplayer by default with realtime p2p state synchronization! + Graph data lets you use key/value, tables, documents, videos, & more! + Local-first, offline, and decentralized with end-to-end encryption. Decentralized alternatives to [Zoom](https://www.zdnet.com/article/era-hatches-meething-an-open-source-browser-based-video-conferencing-system/), [Reddit](https://notabug.io/t/whatever/comments/36588a16b9008da4e3f15663c2225e949eca4a15/gpu-bot-test), [Instagram](https://iris.to/), [Slack](https://iris.to/), [YouTube](https://d.tube/), [Stripe](https://twitter.com/marknadal/status/1422717427427647489), [Wikipedia](https://news.ycombinator.com/item?id=17685682), Facebook [Horizon](https://twitter.com/marknadal/status/1424476179189305347) and more have already pushed terabytes of daily P2P traffic on GUN. We are a [friendly community](http://chat.gun.eco/) creating a [free fun future for freedom](https://youtu.be/1HJdrBk3BlE):
## Quickstart GUN is *super easy* to get started with: - Try the [interactive tutorial](https://gun.eco/docs/Todo-Dapp) in the browser (**5min** ~ average developer). - Or `npm install gun` and run the examples with `cd node_modules/gun && npm start` (**5min** ~ average developer). > **Note:** If you don't have [node](http://nodejs.org/) or [npm](https://www.npmjs.com/), read [this](https://github.com/amark/gun/blob/master/examples/install.sh) first. > If the `npm` command line didn't work, you may need to `mkdir node_modules` first or use `sudo`. - An online demo of the examples are available here: http://try.axe.eco/ - Or write a quick app: ([try now in a playground](https://jsbin.com/kadobamevo/edit?js,console)) ```html ``` - Or try something **mind blowing**, like saving circular references to a table of documents! ([play](http://jsbin.com/wefozepume/edit?js,console)) ```javascript cat = {name: "Fluffy", species: "kitty"}; mark = {boss: cat}; cat.slave = mark; // partial updates merge with existing data! gun.get('mark').put(mark); // access the data as if it is a document. gun.get('mark').get('boss').get('name').once(function(data, key){ // `once` grabs the data once, no subscriptions. console.log("Mark's boss is", data); }); // traverse a graph of circular references! gun.get('mark').get('boss').get('slave').once(function(data, key){ console.log("Mark is the cat's slave!", data); }); // add both of them to a table! gun.get('list').set(gun.get('mark').get('boss')); gun.get('list').set(gun.get('mark')); // grab each item once from the table, continuously: gun.get('list').map().once(function(data, key){ console.log("Item:", data); }); // live update the table! gun.get('list').set({type: "cucumber", goal: "jumping cat"}); ``` Want to keep building more? **Jump to [THE DOCUMENTATION](#documentation)!** # About First & foremost, GUN is **a community of the nicest and most helpful people** out there. So [I want to invite you](http://chat.gun.eco) to come tell us about what **you** are working on & wanting to build (new or old school alike! Just be nice as well.) and ask us your questions directly. :)


Watch the 100 second intro!

The GUN ecosystem stack is a collection of independent and modular tools covering everything from [CRDT](https://crdt.tech/) [conflict resolution](https://gun.eco/distributed/matters.html), [cryptographic security](https://gun.eco/docs/Cartoon-Cryptography) & [encryption](https://gun.eco/docs/SEA), [radix storage serialization](https://gun.eco/docs/RAD), [mesh networking](https://gun.eco/docs/DAM) & [routing algorithms](https://gun.eco/docs/Routing), to distributed systems [correctness & load testing](https://github.com/gundb/panic-server), CPU scheduled [JSON parser](https://github.com/amark/gun/blob/master/lib/yson.js) to prevent UI lag, and more!
On that note, let's get some official shout outs covered first: ### Support

Thanks to:
              
Robert Heessels, Lorenzo Mangani, NLnet Foundation, Sam Liu, Daniel Dombrowsky, Vincent Woo, AJ ONeal, Bill Ottman, Mike Lange, Sean Matheson, Alan Mimms, Dário Freire, John Williamson, Robin Bron, Elie Makhoul, Mike Staub, Bradley Matusiak, Jeff Cook, Nico, Aaron Artille, Tim Robinson, Fabian Stamm, Mike Staub, Hunter Owens, Jacob Millner, Gerrit Balindt, Gabriel Lemon, Murage Martin, Jason Stallings

- Join others in sponsoring code: https://www.patreon.com/gunDB ! - Ask questions: http://stackoverflow.com/questions/tagged/gun ? - Found a bug? Report at: https://github.com/amark/gun/issues ; - **Need help**? Chat with us: http://chat.gun.eco . ### History [GUN](https://gun.eco) was created by [Mark Nadal](https://twitter.com/marknadal) in 2014 after he had spent 4 years trying to get his collaborative web app to scale up with traditional databases. After he realized [Master-Slave database architecture causes one big bottleneck](https://gun.eco/distributed/matters.html), he (as a complete newbie outsider) naively decided **to question the status quo** and shake things up with controversial, heretical, and contrarian experiments: **The NoDB** - no master, no servers, no "single source of truth", not built with a real programming language or real hardware, no DevOps, no locking, not *just* SQL or NoSQL but both (**all** - graphs, documents, tables, key/value). The goal was to build a P2P database that could survive living inside **any** browser, and could correctly sync data between **any** device after assuming **any** offline-first activity. Technically, **GUN is a graph synchronization protocol** with a *lightweight embedded engine*, capable of doing *[20M+ API ops/sec](https://gun.eco/docs/Performance)* in **just ~9KB gzipped size**. ## Documentation

API reference

Tutorials

Examples

GraphQL

Electron

React & Native

Vue

Svelte

Webcomponents

CAP Theorem Tradeoffs

How Data Sync Works

How GUN is Built

Crypto Auth

Modules

Roadmap

This would not be possible without **community contributors**, big shout out to: **[ajmeyghani](https://github.com/ajmeyghani) ([Learn GUN Basics with Diagrams](https://medium.com/@ajmeyghani/gundb-a-graph-database-in-javascript-3860a08d873c))**; **[anywhichway](https://github.com/anywhichway) ([Block Storage](https://github.com/anywhichway/gun-block))**; **[beebase](https://github.com/beebase) ([Quasar](https://github.com/beebase/gun-vuex-quasar))**; **[BrockAtkinson](https://github.com/BrockAtkinson) ([brunch config](https://github.com/BrockAtkinson/brunch-gun))**; **[Brysgo](https://github.com/brysgo) ([GraphQL](https://github.com/brysgo/graphql-gun))**; **[d3x0r](https://github.com/d3x0r) ([SQLite](https://github.com/d3x0r/gun-db))**; **[forrestjt](https://github.com/forrestjt) ([file.js](https://github.com/amark/gun/blob/master/lib/file.js))**; **[hillct](https://github.com/hillct) (Docker)**; **[JosePedroDias](https://github.com/josepedrodias) ([graph visualizer](http://acor.sl.pt:9966))**; **[JuniperChicago](https://github.com/JuniperChicago) ([cycle.js bindings](https://github.com/JuniperChicago/cycle-gun))**; **[jveres](https://github.com/jveres) ([todoMVC](https://github.com/jveres/todomvc))**; **[kristianmandrup](https://github.com/kristianmandrup) ([edge](https://github.com/kristianmandrup/gun-edge))**; **[Lightnet](https://github.com/Lightnet)** ([Awesome Vue User Examples](https://glitch.com/edit/#!/jsvuegunui?path=README.md:1:0) & [User Kitchen Sink Playground](https://gdb-auth-vue-node.glitch.me/)); **[lmangani](https://github.com/lmangani) ([Cytoscape Visualizer](https://github.com/lmangani/gun-scape), [Cassandra](https://github.com/lmangani/gun-cassandra), [Fastify](https://github.com/lmangani/fastify-gundb), [LetsEncrypt](https://github.com/lmangani/polyGun-letsencrypt))**; **[mhelander](https://github.com/mhelander) ([SEA](https://github.com/amark/gun/blob/master/sea.js))**; [omarzion](https://github.com/omarzion) ([Sticky Note App](https://github.com/omarzion/stickies)); [PsychoLlama](https://github.com/PsychoLlama) ([LevelDB](https://github.com/PsychoLlama/gun-level)); **[RangerMauve](https://github.com/RangerMauve) ([schema](https://github.com/gundb/gun-schema))**; **[robertheessels](https://github.com/swifty) ([gun-p2p-auth](https://github.com/swifty/gun-p2p-auth))**; **[rogowski](https://github.com/rogowski) (AXE)**; [sbeleidy](https://github.com/sbeleidy); **[sbiaudet](https://github.com/sbiaudet) ([C# Port](https://github.com/sbiaudet/cs-gun))**; **[Sean Matheson](https://github.com/ctrlplusb) ([Observable/RxJS/Most.js bindings](https://github.com/ctrlplusb/gun-most))**; **[Shadyzpop](https://github.com/Shadyzpop) ([React Native example](https://github.com/amark/gun/tree/master/examples/react-native))**; **[sjones6](https://github.com/sjones6) ([Flint](https://github.com/sjones6/gun-flint))**; RIP **[Stefdv](https://github.com/stefdv) (Polymer/web components)**; **[zrrrzzt](https://github.com/zrrrzzt) ([JWT Auth](https://gist.github.com/zrrrzzt/6f88dc3cedee4ee18588236756d2cfce))**; **[xmonader](https://github.com/xmonader) ([Python Port](https://github.com/xmonader/pygundb))**; I am missing many others, apologies, will be adding them soon! This list is infinitely old & way out of date, if you want to be listed in it please make a PR! :) ## Testing You will need to `npm install -g mocha` first. Then in the gun root folder run `npm test`. Tests will trigger persistent writes to the DB, so subsequent runs of the test will fail. You must clear the DB before running the tests again. This can be done by running `rm -rf *data*` command in the project directory. ## Shims > These are only needed for NodeJS & React Native, they shim the native Browser WebCrypto API. If you want to use [SEA](https://gun.eco/docs/SEA) for `User` auth and security, you will need to install: `npm install @peculiar/webcrypto --save` Please see [our React Native docs](https://gun.eco/docs/React-Native) for installation instructions! Then you can require [SEA](https://gun.eco/docs/SEA) without an error: ```javascript GUN = require('gun/gun'); SEA = require('gun/sea'); ``` ## Deploy > Note: The default examples that get auto-deployed on `npm start` CDN-ify all GUN files, modules, & storage. > Note: Moving forward, AXE will start to automatically cluster your peer into a shared DHT. You may want to disable this to run an isolated network. > Note: When deploying a web application using GUN on a cloud provider, you may have to set `CI=false` in your `.env`. This prevents GUN-specific warnings from being treated as errors when deploying your app. You may also resolve this by modifying your webpack config to not try to build the GUN dependencies. To quickly spin up a GUN relay peer for your development team, utilize [Heroku](http://heroku.com), [Docker](http://docker.com), or any others listed below. Or some variant thereof [Dokku](http://dokku.viewdocs.io/dokku/), K8s, etc. ! Or use all of them so your relays are decentralized too! ### Linux `SSH` into the home directory of a clean OS install with `sudo` ability. Set any environment variables you need (see below), then do: ```bash curl -o- https://raw.githubusercontent.com/amark/gun/master/examples/install.sh | bash ``` > Read [install.sh](https://github.com/amark/gun/blob/master/examples/install.sh) first! > If `curl` is not found, *copy&paste* the contents of install.sh into your ssh. You can now safely `CTRL+A+D` to escape without stopping the peer. To stop everything `killall screen` or `killall node`. Environment variables may need to be set like `export HTTPS_CERT=~/cert.pem HTTPS_KEY=~/key.pem PORT=443`. You can also look at a sample [nginx](https://gun.eco/docs/nginx) config. For production deployments, you probably will want to use something like `pm2` or better to keep the peer alive after machine reboots. ### [Dome](https://www.trydome.io/) [Deploy GUN in one-click](https://app.trydome.io/signup?package=gun) with [Dome](https://trydome.io) and receive a free trial: [![Deploy to Dome](https://trydome.io/button.svg)](https://app.trydome.io/signup?package=gun) ### [Heroku](https://www.heroku.com/) [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/amark/gun) > Heroku deletes your data every 15 minutes, one way to fix this is by adding [cheap storage](https://gun.eco/docs/Using-Amazon-S3-for-Storage). Or: ```bash git clone https://github.com/amark/gun.git cd gun heroku create git push -f heroku HEAD:master ``` Then visit the URL in the output of the 'heroku create' step, in a browser. Make sure to set any environment config vars in the settings tab. ### [Zeet.co](https://www.zeet.co/) [![Deploy](https://deploy.zeet.co/gun.svg)](https://deploy.zeet.co/?url=https://github.com/amark/gun) Then visit the URL in the output of the 'now --npm' step, in your browser. ### [Docker](https://www.docker.com/) > Warning: Docker image is community contributed and may be old with missing security updates, please check version numbers to compare. [![Docker Automated build](https://img.shields.io/docker/automated/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/) [![](https://images.microbadger.com/badges/image/gundb/gun.svg)](https://microbadger.com/images/gundb/gun "Get your own image badge on microbadger.com") [![Docker Pulls](https://img.shields.io/docker/pulls/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/) [![Docker Stars](https://img.shields.io/docker/stars/gundb/gun.svg)](https://hub.docker.com/r/gundb/gun/) Pull from the [Docker Hub](https://hub.docker.com/r/gundb/gun/) [![](https://images.microbadger.com/badges/commit/gundb/gun.svg)](https://microbadger.com/images/gundb/gun). Or: ```bash docker run -p 8765:8765 gundb/gun ``` Or build the [Docker](https://docs.docker.com/engine/installation/) image locally: ```bash git clone https://github.com/amark/gun.git cd gun docker build -t myrepo/gundb:v1 . docker run -p 8765:8765 myrepo/gundb:v1 ``` Or, if you prefer your Docker image with metadata labels (Linux/Mac only): ```bash npm run docker docker run -p 8765:8765 username/gun:git ``` Then visit [http://localhost:8765](http://localhost:8765) in your browser. ## License Designed with ♥ by Mark Nadal, the GUN team, and many amazing contributors. Openly licensed under [Zlib / MIT / Apache 2.0](https://github.com/amark/gun/blob/master/LICENSE.md). [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Famark%2Fgun.svg?size=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Famark%2Fgun?ref=badge_large) [YouTube](https://www.youtube.com/channel/UCQAtpf-zi9Pp4__2nToOM8g) . [Twitter](https://twitter.com/marknadal) ================================================ FILE: RELEASE.md ================================================ Every push or pull request will - run the tests Every push to master will - run the tests - publish the latest docker image to dockerhub Creating a tag that starts with `v` will - create a new github release - publish the release to npm - publish the release to dockerhub Creating a release from the github web interface will - publish the release to npm - publish the release to dockerhub Creating the release for version `0.2021.001` from the command line works as follows git tag v0.2021.001 git push --tags ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Introduction Security is our top priority. We are committed to ensuring that our project is as secure as possible for everyone who uses it. This document outlines our security policy and procedures for dealing with security issues. ## Supported Versions We provide security updates for the following versions of our project: | Version | Supported | | ------- | ------------------ | | 0.2020.x| :white_check_mark: | | < 0.2020| :x: | ## Reporting a Vulnerability If you discover a vulnerability, we would like to know about it so we can take steps to address it as quickly as possible. ### Report Format When reporting vulnerabilities, please include the following details: - Description of the vulnerability - Steps to reproduce the issue - Potential impact if left unaddressed - Suggested mitigation or resolution if any ### Response Time We aim to confirm the receipt of your vulnerability report within 48 hours. Depending on the severity and complexity of the issue, we strive to investigate the issue and provide an initial response within a week. ### Disclosure Policy If the vulnerability is confirmed, we will work on a fix and plan a release. We ask that you do not publicly disclose the issue until it has been addressed by us. ## Security Practices We follow industry-standard security practices, including regular audits of the services and features we provide, to maintain the trust of our users. ## Security Updates We will communicate any security updates through our standard communication channels, including our project's release notes and official website. ## Conclusion We greatly value the work of security researchers and believe that responsible disclosure of vulnerabilities is a valuable contribution to the security of the Internet. We encourage users to contribute to the security of our project by reporting any security-related issues to us. ================================================ FILE: app.json ================================================ { "name": "gun-server", "website": "http://gun.eco/", "repository": "https://github.com/amark/gun", "logo": "https://avatars3.githubusercontent.com/u/8811914", "keywords": ["node", "gun", "gunDB", "database","graph","offline-first"], "description": "Javascript, Offline-First Javascript Graph Database Server Peer", "env": { "NPM_CONFIG_PRODUCTION": { "description": "If you do not want default features, set to \"true\".", "value": "false" }, "PEERS": { "description": "Comma-separated list of peer urls to connect to", "required": false } } } ================================================ FILE: as.js ================================================ ;(function(){ function as(el, gun, cb, opt){ el = $(el); if(gun === as.gui && as.el && as.el.is(el)){ return } opt = opt || {}; opt.match = opt.match || '{{ '; opt.end = opt.end || ' }}'; ;(function(){ // experimental function nest(t, s,e, r, i,tmp,u){ if(r && !r.length){ return t||'' } if(!t){ return [] } e = e || s; i = t.indexOf(s, i||0); if(0 > i){ return [] } tmp = t.indexOf(e, i+1); if(!r){ return [t.slice(i+s.length, tmp)].concat(nest(t, s,e, r, tmp,tmp,u)) } return t.slice(0,i)+r[0]+nest(t.slice(tmp+e.length), s,e, r.slice(1), 0,tmp,u); } /* experimental */ function template(tag, attr){ var html = (tag = $(tag))[0].outerHTML, sub, tmp; if(html && (0 > html.indexOf(opt.match))){ return } if(!attr){ $.each(tag[0].attributes, function(i,v){ if(!v){ return } if(!nest(v.value, opt.match, opt.end).length){ return } template(tag, v.name) }); if((sub = tag.children()).length){ return sub.each(function(){ template(this) }); } } var data = [], plate = attr? tag.attr(attr) : tag.html(); tmp = nest(plate, opt.match, opt.end); if(!tmp.length){ return } $.each(tmp, function(pos, match){ var expr = match.split(' '); var path = (expr[0]).split('.'); if(expr = expr.slice(1).join(' ')){ expr = new Function("_", "b", "return (_)" + expr); } var val = (expr && expr('')) || ''; data.push(val); if(!attr){ tag.text(val) } var ref = gun, sup = [], tmp; if(tmp = tag.attr('name')){ sup.push(tmp) } tag.parents("[name]").each(function(){ sup.push($(this).attr('name')); }); $.each(path = sup.reverse().concat(path), function(i,v){ ref = ref.get(v); }); ref.on(function(v){ v = data[pos] = expr? expr(v) : v; var tmp = nest(plate, opt.match, opt.end, data); if(attr){ tag.attr(attr, tmp); } else { tag.text(tmp); } }); }); } template(el); }()); as.gui = gun; as.el = el; if(el.data('as')){ el.html(el.data('as').fresh); } else { el.data('as', { fresh: el.html() }) } el.find("[name]").each(function(){ if($(this).find("[name]").length){ return } var name = $(this), parents = name.parents("[name]"), path = [], ref = gun; path.push(name.attr('name')); parents.each(function(){ path.push($(this).attr('name')); }); path = path.reverse(); path.forEach(function(key){ if('#' === key){ ref = ref.map() } else { ref = ref.get(key); } }); var many = path.slice().reverse().indexOf('#'), model; many = (0 < ++many)? many : false; if(many){ model = name.closest("[name='#']"); model = model.data('model') || model.data('model', {$: model.clone(), on: model.parent(), has: {}}).hide().data('model'); } ref.get(function(at){ var data = at.put, key = at.get, gui = at.gun || at.$, ui = name, back; if(model){ ui = model.has[(gui._).id]; if(!ui){ back = gui.back(many - 1); ui = model.has[(back._).id]; if(!ui){ if(!(back._).get){ return } ui = (model.has[(back._).id] = model.$.clone(true).prependTo(model.on)); } ui = ui.find("[name='"+key+"']").first(); model.has[(gui._).id] = ui; } } ui.data('gun', gui); if(ui.data('was') === data){ return } if(many && ui.is('.sort')){ var up = ui.closest("[name='#']"); var tmp = as.sort(data, up.parent().children().last()); tmp? up.insertAfter(tmp) : up.prependTo(up.parent()); } if(as.lock === gui){ return } if(!(data && data instanceof Object)){ (ui[0] && u === ui[0].value)? ui.text(data) : ui.val(data); } ui.data('was', data); if(cb){ cb(data, key, ui); } }); }); } as.wait = function(cb, wait, to){ return function(a,b,c){ var me = as.typing = this; clearTimeout(to); to = setTimeout(function(){ cb.call(me, a,b,c); as.typing = me = false; }, wait || 200); } } as.sort = function sort(num, li){ return parseFloat(num) >= parseFloat($(li).find('.sort').text() || -Infinity)? li : sort(num, li.prev()) } $(document).on('keyup', 'input, textarea, [contenteditable]', as.wait(function(){ var el = $(this); var data = (el[0] && u === el[0].value)? el.text() : el.val(); var g = el.data('gun'); if(!g){ return } as.lock = g; g.put(data); }, 99)); //$(document).on('submit', 'form', function(e){ e.preventDefault() }); var u; window.as = as; $.as = as; }()); ;(function(){ $(document).on('click', 'a, button', function(e){ var tmp = $(this).attr('href') || ''; if(0 === tmp.indexOf('http')){ return } e.preventDefault(); r(tmp); }); function r(href){ if(!href){ return } if(href[0] == '#'){ href = href.slice(1) } var h = href.split('/')[0]; $('.page').hide(); $('#' + h).show(); if(r.on === h){ return } location.hash = href; (r.page[h] || {on:function(){}}).on(); r.on = h; return r; }; r.page = function(h, cb){ r.page[h] = r.page[h] || {on: cb}; return r; } r.render = function(id, model, onto, data){ var $data = $( $('#' + id).get(0) || $('.model').find(model).clone(true).attr('id', id).appendTo(onto) ); $.each(data, function(field, val){ if($.isPlainObject(val)){ return } $data.find("[name='" + field + "']").val(val).text(val); }); return $data; } window.onhashchange = function(){ r(location.hash.slice(1)) }; $.as && ($.as.route = r); if(window.as){ as.route = r; } else { $.route = r; } }()); ;$(function(){ $('.page').not(':first').hide(); $.as.route(location.hash.slice(1)); $(JOY.start = JOY.start || function(){ $.as(document, gun, null, JOY.opt) }); if($('body').attr('peers')){ (console.warn || console.log)('Warning: Please upgrade to https://github.com/eraeco/joydb#peers !') } }); ;(function(){ // need to isolate into separate module! var joy = window.JOY = function(){}; joy.auth = function(a,b,cb,o){ if(!o){ o = cb ; cb = 0 } if(o === true){ gun.user().create(a, b); return; } gun.user().auth(a,b, cb,o); } var opt = joy.opt = window.CONFIG || {}, peers; $('link[type=peer]').each(function(){ (peers || (peers = [])).push($(this).attr('href')) }); !window.gun && (opt.peers = opt.peers || peers || (function(){ (console.warn || console.log)('Warning: No peer provided, defaulting to DEMO peer. Do not run in production, or your data will be regularly wiped, reset, or deleted. For more info, check https://github.com/eraeco/joydb#peers !'); return ['https://gunjs.herokuapp.com/gun']; }())); window.gun = window.gun || Gun(opt); gun.on('auth', function(ack){ console.log("Your namespace is publicly available at", ack.soul); }); }()); ================================================ FILE: axe.js ================================================ ;(function(){ var sT = setTimeout || {}, u; if(typeof window !== ''+u){ sT.window = window } var AXE = (sT.window||'').AXE || function(){}; if(AXE.window = sT.window){ AXE.window.AXE = AXE } var Gun = (AXE.window||'').GUN || require('./gun'); (Gun.AXE = AXE).GUN = AXE.Gun = Gun; //if(!Gun.window){ try{ require('./lib/axe') }catch(e){} } if(!Gun.window){ require('./lib/axe') } Gun.on('opt', function(at){ start(at) ; this.to.next(at) }); // make sure to call the "next" middleware adapter. function start(root){ if(root.axe){ return } var opt = root.opt, peers = opt.peers; if(false === opt.axe){ return } if(!Gun.window){ return } // handled by ^ lib/axe.js var w = Gun.window, lS = w.localStorage || opt.localStorage || {}, loc = w.location || opt.location || {}, nav = w.navigator || opt.navigator || {}; var axe = root.axe = {}, tmp, id; var mesh = opt.mesh = opt.mesh || Gun.Mesh(root); // DAM! tmp = peers[id = loc.origin + '/gun'] = peers[id] || {}; tmp.id = tmp.url = id; tmp.retry = tmp.retry || 0; tmp = peers[id = 'http://localhost:8765/gun'] = peers[id] || {}; tmp.id = tmp.url = id; tmp.retry = tmp.retry || 0; Gun.log.once("AXE", "AXE enabled: Trying to find network via (1) local peer (2) last used peers (3) a URL parameter, and last (4) hard coded peers."); Gun.log.once("AXEWarn", "Warning: AXE is in alpha, use only for testing!"); var last = lS.peers || ''; if(last){ last += ' ' } last += ((loc.search||'').split('peers=')[1]||'').split('&')[0]; root.on('bye', function(peer){ this.to.next(peer); if(!peer.url){ return } // ignore WebRTC disconnects for now. if(!nav.onLine){ peer.retry = 1 } if(peer.retry){ return } if(axe.fall){ delete axe.fall[peer.url || peer.id] } (function next(){ if(!axe.fall){ setTimeout(next, 9); return } // not found yet var fall = Object.keys(axe.fall||''), one = fall[(Math.random()*fall.length) >> 0]; if(!fall.length){ lS.peers = ''; one = 'https://gunjs.herokuapp.com/gun' } // out of peers if(peers[one]){ next(); return } // already choose mesh.hi(one); }()); }); root.on('hi', function(peer){ // TEMPORARY! Try to connect all peers. this.to.next(peer); if(!peer.url){ return } // ignore WebRTC disconnects for now. return; // DO NOT COMMIT THIS FEATURE YET! KEEP TESTING NETWORK PERFORMANCE FIRST! (function next(){ if(!peer.wire){ return } if(!axe.fall){ setTimeout(next, 9); return } // not found yet var one = (next.fall = next.fall || Object.keys(axe.fall||'')).pop(); if(!one){ return } setTimeout(next, 99); mesh.say({dam: 'opt', opt: {peers: one}}, peer); }()); }); function found(text){ axe.fall = {}; ((text||'').match(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/ig)||[]).forEach(function(url){ axe.fall[url] = {url: url, id: url, retry: 0}; // RETRY }); return; // TODO: Finish porting below? Maybe not. Object.keys(last.peers||'').forEach(function(key){ tmp = peers[id = key] = peers[id] || {}; tmp.id = tmp.url = id; }); tmp = peers[id = 'https://guntest.herokuapp.com/gun'] = peers[id] || {}; tmp.id = tmp.url = id; var mesh = opt.mesh = opt.mesh || Gun.Mesh(root); // DAM! mesh.way = function(msg){ if(root.$ === msg.$ || (msg._||'').via){ mesh.say(msg, opt.peers); return; } var at = (msg.$||'')._; if(!at){ mesh.say(msg, opt.peers); return } if(msg.get){ if(at.axe){ return } // don't ask for it again! at.axe = {}; } mesh.say(msg, opt.peers); } } if(last){ found(last); return } try{ fetch(((loc.search||'').split('axe=')[1]||'').split('&')[0] || loc.axe || 'https://raw.githubusercontent.com/wiki/amark/gun/volunteer.dht.md').then(function(res){ return res.text() }).then(function(text){ found(lS.peers = text); }).catch(function(){ found(); // nothing })}catch(e){found()} } var empty = {}, yes = true; try{ if(typeof module != ''+u){ module.exports = AXE } }catch(e){} }()); ================================================ FILE: bower.json ================================================ { "name": "gun", "main": "gun.js", "version": "0.1.5", "homepage": "http://gunDB.io", "authors": [ { "name": "Mark Nadal", "email": "mark@accelsor.com" }, { "name": "Alex LaFroscia", "email": "alex@lafroscia.com" } ], "repository": { "type": "git", "url": "https://github.com/amark/gun" }, "description": "A distributed, embedded, graph database engine.", "moduleType": [ "globals" ], "keywords": [ "graph", "database", "gun", "gundb", "nodb" ], "license": "MIT", "ignore": [ "**/.*", "node_modules", "bower_components", "test", "tests" ] } ================================================ FILE: browser.js ================================================ // if(!(typeof navigator == "undefined") && navigator.product == "ReactNative"){ // require("./lib/mobile.js"); // } module.exports = require('./gun.js'); ================================================ FILE: examples/.gitignore ================================================ node_modules/* npm-debug.log *data.json ================================================ FILE: examples/Main.js ================================================ import { render } from './iris/js/lib/preact.js'; import { Router, route } from './iris/js/lib/preact-router.es.js'; import { createHashHistory } from './iris/js/lib/history.production.min.js'; import { Component } from './iris/js/lib/preact.js'; import { Link } from './iris/js/lib/preact.match.js'; import Helpers from './iris/js/Helpers.js'; import { html } from './iris/js/Helpers.js'; import QRScanner from './iris/js/QRScanner.js'; import PeerManager from './iris/js/PeerManager.js'; import Session from './iris/js/Session.js'; import { translate as t } from './iris/js/Translation.js'; import Settings from './iris/js/views/Settings.js'; import LogoutConfirmation from './iris/js/views/LogoutConfirmation.js'; import Chat from './iris/js/views/Chat.js'; import Store from './iris/js/views/Store.js'; import Checkout from './iris/js/views/Checkout.js'; import Product from './iris/js/views/Product.js'; import Login from './iris/js/views/Login.js'; import Profile from './iris/js/views/Profile.js'; import Group from './iris/js/views/Group.js'; import Message from './iris/js/views/Message.js'; import Follows from './iris/js/views/Follows.js'; import Feed from './iris/js/views/Feed.js'; import About from './iris/js/views/About.js'; import Explorer from './iris/js/views/Explorer.js'; import Contacts from './iris/js/views/Contacts.js'; import Torrent from './iris/js/views/Torrent.js'; import VideoCall from './iris/js/components/VideoCall.js'; import Identicon from './iris/js/components/Identicon.js'; import MediaPlayer from './iris/js/components/MediaPlayer.js'; import Footer from './iris/js/components/Footer.js'; import State from './iris/js/State.js'; import Icons from './iris/js/Icons.js'; const userAgent = navigator.userAgent.toLowerCase(); const isElectron = (userAgent.indexOf(' electron/') > -1); if (!isElectron && ('serviceWorker' in navigator)) { window.addEventListener('load', function() { navigator.serviceWorker.register('iris/serviceworker.js') .catch(function(err) { // registration failed :( console.log('ServiceWorker registration failed: ', err); }); }); } State.init(); Session.init({autologin: true}); PeerManager.init(); Helpers.checkColorScheme(); const APPLICATIONS = [ // TODO: move editable shortcuts to State.local gun {url: '/', text: t('home'), icon: Icons.home}, {url: '/feed', text: t('feed'), icon: Icons.feed}, {url: '/media', text: t('media'), icon: Icons.play}, {url: '/settings', text: t('settings'), icon: Icons.settings}, {url: '/store', text: t('store'), icon: Icons.store}, {url: '/explorer', text: t('explorer'), icon: Icons.folder}, {url: '/chat', text: t('messages'), icon: Icons.chat}, // {url: '/store', text: t('store'), icon: Icons.store}, // restore when it works! {}, {url: '../stats.html', text: 'Gun node stats'}, {url: '../iris/index.html', text: 'Iris', icon: html``}, {url: '../infinite-scroll/index.html', text: 'Infinite scroll'}, {url: '../chat/index.html', text: 'Chat'}, {url: '../game/space.html', text: 'Space'}, {}, {url: 'https://gun.eco/docs/', text: 'Gun documentation'}, {url: 'https://examples.iris.to/components/', text: 'Iris web components'} ]; const HomeView = () => { return html`

Hello, world!

Here you can find sample applications and utilities for GUN.

If you need any help, please feel free to join the GUN community chat: http://chat.gun.eco

Explorer

Explore the data saved on the GUN database. Open to the side while using an application and see the data change in real-time.

Space

Spaceflight game. Open in 2 or more browser windows.

Iris

Decentralized Twitter/Instagram. Provides modular components that can be reused in other applications (including this one).

Chat

Shoutbox!

`; }; class MenuView extends Component { componentDidMount() { State.local.get('showMenu').on(showMenu => this.setState({showMenu})); } render() { const pub = Session.getPubKey(); return html`
<${Identicon} str=${pub} width=40/>

${APPLICATIONS.map(a => { if (a.url) { return html` ${a.icon || Icons.circle} ${a.text} `; } else { return html`

`; } })}
`; } }; class Main extends Component { constructor() { super(); this.showMenu = false; } componentDidMount() { State.local.get('loggedIn').on(loggedIn => this.setState({loggedIn})); } handleRoute(e) { let activeRoute = e.url; if (!activeRoute && window.location.hash) { return route(window.location.hash.replace('#', '')); // bubblegum fix back navigation } document.title = 'Iris'; if (activeRoute && activeRoute.length > 1) { document.title += ' - ' + Helpers.capitalize(activeRoute.replace('/', '')); } State.local.get('activeRoute').put(activeRoute); QRScanner.cleanupScanner(); } onClickOverlay() { if (this.state.showMenu) { this.setState({showMenu: false}); } } toggleMenu(show) { this.setState({showMenu: typeof show === 'undefined' ? !this.state.showMenu : show}); } render() { const content = this.state.loggedIn ? html`
State.local.get('showMenu').put(this.showMenu = !this.showMenu)} style="padding: 5px;cursor:pointer;" viewBox="0 -53 384 384" width="40px">
<${MenuView}/>
<${Router} history=${createHashHistory()} onChange=${e => this.handleRoute(e)}> <${HomeView} path="/"/> <${Feed} path="/feed"/> <${Feed} path="/search/:term?/:type?"/> <${Feed} path="/media" index="media"/> <${Login} path="/login"/> <${Chat} path="/chat/:id?"/> <${Message} path="/post/:hash"/> <${Torrent} path="/torrent/:id"/> <${About} path="/about"/> <${Settings} path="/settings"/> <${LogoutConfirmation} path="/logout"/> <${Profile} path="/profile/:id?" tab="profile"/> <${Profile} path="/replies/:id?" tab="replies"/> <${Profile} path="/likes/:id?" tab="likes"/> <${Profile} path="/media/:id" tab="media"/> <${Group} path="/group/:id?"/> <${Store} path="/store/:store?"/> <${Checkout} path="/checkout/:store?"/> <${Product} path="/product/:product/:store"/> <${Product} path="/product/new" store=Session.getPubKey()/> <${Explorer} path="/explorer/:node"/> <${Explorer} path="/explorer"/> <${Follows} path="/follows/:id"/> <${Follows} followers=${true} path="/followers/:id"/> <${Contacts} path="/contacts"/>
<${VideoCall}/> ` : ''; return html`
${content}
`; } } render(html`<${Main}/>`, document.body); $('body').css('opacity', 1); // use opacity because setting focus on display: none elements fails ================================================ FILE: examples/angular/.angular-cli.json ================================================ { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "project": { "name": "angular" }, "apps": [ { "root": "src", "outDir": "dist", "assets": [ "assets", "favicon.ico" ], "index": "index.html", "main": "main.ts", "polyfills": "polyfills.ts", "test": "test.ts", "tsconfig": "tsconfig.app.json", "testTsconfig": "tsconfig.spec.json", "prefix": "app", "styles": [ "styles.css" ], "scripts": [], "environmentSource": "environments/environment.ts", "environments": { "dev": "environments/environment.ts", "prod": "environments/environment.prod.ts" } } ], "e2e": { "protractor": { "config": "./protractor.conf.js" } }, "lint": [ { "project": "src/tsconfig.app.json", "exclude": "**/node_modules/**" }, { "project": "src/tsconfig.spec.json" }, { "project": "e2e/tsconfig.e2e.json" } ], "test": { "karma": { "config": "./karma.conf.js" } }, "defaults": { "styleExt": "css", "component": {} } } ================================================ FILE: examples/angular/.editorconfig ================================================ # Editor configuration, see http://editorconfig.org root = true [*] charset = utf-8 indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.md] max_line_length = off trim_trailing_whitespace = false ================================================ FILE: examples/angular/.gitignore ================================================ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /tmp /out-tsc # dependencies /node_modules # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json # misc /.sass-cache /connect.lock /coverage /libpeerconnection.log npm-debug.log testem.log /typings # e2e /e2e/*.js /e2e/*.map # System Files .DS_Store Thumbs.db ================================================ FILE: examples/angular/README.md ================================================ # Angular This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.0. ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. ## Code scaffolding Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`. ## Build Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. ## Running unit tests Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). ## Running end-to-end tests Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). Before running the tests make sure you are serving the app via `ng serve`. ## Further help To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). ================================================ FILE: examples/angular/e2e/app.e2e-spec.ts ================================================ import { AngularPage } from './app.po'; describe('angular App', () => { let page: AngularPage; beforeEach(() => { page = new AngularPage(); }); it('should display message saying app works', () => { page.navigateTo(); expect(page.getParagraphText()).toEqual('app works!'); }); }); ================================================ FILE: examples/angular/e2e/app.po.ts ================================================ import { browser, element, by } from 'protractor'; export class AngularPage { navigateTo() { return browser.get('/'); } getParagraphText() { return element(by.css('app-root h1')).getText(); } } ================================================ FILE: examples/angular/e2e/tsconfig.e2e.json ================================================ { "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/e2e", "module": "commonjs", "target": "es5", "types":[ "jasmine", "node" ] } } ================================================ FILE: examples/angular/example_package.json ================================================ { "name": "angular", "version": "0.0.0", "license": "MIT", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/common": "^4.1.0", "@angular/compiler": "^4.1.0", "@angular/core": "^4.1.0", "@angular/forms": "^4.1.0", "@angular/http": "^4.1.0", "@angular/platform-browser": "^4.1.0", "@angular/platform-browser-dynamic": "^4.1.0", "@angular/router": "^4.1.0", "core-js": "^2.4.1", "express-http-proxy": "^1.0.1", "gun": "https://github.com/amark/gun.git#master", "ngx-pipes": "^2.0.5", "rxjs": "^5.3.0", "underscore": "^1.8.3", "zone.js": "^0.8.9" }, "devDependencies": { "@angular/cli": "1.0.0", "@angular/compiler-cli": "^4.1.0", "@types/jasmine": "2.5.38", "@types/node": "~6.0.60", "@types/underscore": "^1.8.0", "codelyzer": "^2.1.1", "jasmine-core": "^2.6.1", "jasmine-spec-reporter": "^4.0.0", "karma": "^1.6.0", "karma-chrome-launcher": "~2.0.0", "karma-cli": "~1.0.1", "karma-coverage-istanbul-reporter": "^1.2.0", "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.1.0", "ts-node": "^3.0.2", "tslint": "~4.5.0", "typescript": "^2.3.2" } } ================================================ FILE: examples/angular/karma.conf.js ================================================ // Karma configuration file, see link for more information // https://karma-runner.github.io/0.13/config/configuration-file.html module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular/cli'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('@angular/cli/plugins/karma') ], client:{ clearContext: false // leave Jasmine Spec Runner output visible in browser }, files: [ { pattern: './src/test.ts', watched: false } ], preprocessors: { './src/test.ts': ['@angular/cli'] }, mime: { 'text/x-typescript': ['ts','tsx'] }, coverageIstanbulReporter: { reports: [ 'html', 'lcovonly' ], fixWebpackSourcePaths: true }, angularCli: { environment: 'dev' }, reporters: config.angularCli && config.angularCli.codeCoverage ? ['progress', 'coverage-istanbul'] : ['progress', 'kjhtml'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false }); }; ================================================ FILE: examples/angular/protractor.conf.js ================================================ // Protractor configuration file, see link for more information // https://github.com/angular/protractor/blob/master/lib/config.ts const { SpecReporter } = require('jasmine-spec-reporter'); exports.config = { allScriptsTimeout: 11000, specs: [ './e2e/**/*.e2e-spec.ts' ], capabilities: { 'browserName': 'chrome' }, directConnect: true, baseUrl: 'http://localhost:4200/', framework: 'jasmine', jasmineNodeOpts: { showColors: true, defaultTimeoutInterval: 30000, print: function() {} }, beforeLaunch: function() { require('ts-node').register({ project: 'e2e/tsconfig.e2e.json' }); }, onPrepare() { jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); } }; ================================================ FILE: examples/angular/server.js ================================================ var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 8765; var host = process.env.OPENSHIFT_NODEJS_HOST || process.env.VCAP_APP_HOST || process.env.HOST || 'localhost'; var express = require('express'); var proxy = require('express-http-proxy'); var http = require('http'); var app = express(); var server = http.createServer(app); var Gun = require('gun'); var gun = Gun({ file: 'data.json', web: server }); app.use(Gun.serve); app.use(proxy(host + ':4200')); server.listen(port); console.log('Server started on port ' + port + ' with /gun'); ================================================ FILE: examples/angular/src/app/app.component.css ================================================ html, body { font-size: 14pt; padding: 10px 2.5%;} .hide { display: none; } form .who { width: 10%; } form .what { width: 80%; } ul { list-style: none; padding: 0; } ul .when {color: #555; font-size: 12pt; float: right; display: none; } li:hover .when {display: inline;} ================================================ FILE: examples/angular/src/app/app.component.html ================================================

================================================ FILE: examples/angular/src/app/app.component.spec.ts ================================================ import { TestBed, async } from '@angular/core/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ AppComponent ], }).compileComponents(); })); it('should create the app', async(() => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; expect(app).toBeTruthy(); })); it(`should have as title 'app works!'`, async(() => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; expect(app.title).toEqual('app works!'); })); it('should render title in a h1 tag', async(() => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; expect(compiled.querySelector('h1').textContent).toContain('app works!'); })); }); ================================================ FILE: examples/angular/src/app/app.component.ts ================================================ import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Subscription } from 'rxjs/Subscription'; import Gun from 'gun/gun'; import { GunDb } from 'app/gun.service'; import { on$ } from 'app/gun.helper'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { newTodo = ''; todos = this.db.gun.get('todos'); todos$: Observable = on$(this.todos); todosSub: Subscription; constructor(private db: GunDb) { } ngOnInit() { } add() { if (this.newTodo) { this.todos.get(Gun.text.random()).put(this.newTodo); this.newTodo = ''; } } delete(key: string) { this.todos.get(key).put(null); } sub() { this.todosSub = this.todos$.subscribe(v => console.log(v)); } unsub() { this.todosSub.unsubscribe(); } } ================================================ FILE: examples/angular/src/app/app.module.ts ================================================ import { BrowserModule } from '@angular/platform-browser'; import { NgModule, Injectable } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import { NgPipesModule } from 'ngx-pipes'; import { AppComponent } from './app.component'; import { GunDb } from 'app/gun.service'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, HttpModule, NgPipesModule ], providers: [GunDb], bootstrap: [AppComponent] }) export class AppModule { } ================================================ FILE: examples/angular/src/app/gun.helper.ts ================================================ import { Observable } from 'rxjs/Observable'; import { Gun } from 'gun/gun'; import { pick } from 'underscore'; export function on$(node, cleanup = true): Observable { return Observable.fromEventPattern( h => { // there is no way to off() an on() until at least one value is triggered // so that we can access the event listener to off() it const signal = { stop: false }; node.on((data, key, at, ev) => { if (signal.stop) { ev.off(); } else { // modifying data directly does not seem to work... h(cleanup ? pick(data, (v, k, o) => v !== null && k !== '_') : data); } }); return signal; }, (h, signal) => { signal.stop = true; } ); } export function val$(node): Observable { return new Observable(o => node.val(v => { o.next(v); o.complete(); })); } ================================================ FILE: examples/angular/src/app/gun.service.ts ================================================ import { NgModule, Injectable } from '@angular/core'; import Gun from 'gun/gun'; @Injectable() export class GunDb { readonly gun = Gun(location.origin + '/gun'); } ================================================ FILE: examples/angular/src/assets/.gitkeep ================================================ ================================================ FILE: examples/angular/src/environments/environment.prod.ts ================================================ export const environment = { production: true }; ================================================ FILE: examples/angular/src/environments/environment.ts ================================================ // The file contents for the current environment will overwrite these during build. // The build system defaults to the dev environment which uses `environment.ts`, but if you do // `ng build --env=prod` then `environment.prod.ts` will be used instead. // The list of which env maps to which file can be found in `.angular-cli.json`. export const environment = { production: false }; ================================================ FILE: examples/angular/src/index.html ================================================ Angular Loading... ================================================ FILE: examples/angular/src/main.ts ================================================ import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; import 'rxjs/add/operator/startWith'; import 'rxjs/add/operator/map'; import 'rxjs/add/observable/fromEventPattern'; if (environment.production) { enableProdMode(); } platformBrowserDynamic().bootstrapModule(AppModule); ================================================ FILE: examples/angular/src/polyfills.ts ================================================ /** * This file includes polyfills needed by Angular and is loaded before the app. * You can add your own extra polyfills to this file. * * This file is divided into 2 sections: * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. * 2. Application imports. Files imported after ZoneJS that should be loaded before your main * file. * * The current setup is for so-called "evergreen" browsers; the last versions of browsers that * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. * * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html */ /*************************************************************************************************** * BROWSER POLYFILLS */ /** IE9, IE10 and IE11 requires all of the following polyfills. **/ // import 'core-js/es6/symbol'; // import 'core-js/es6/object'; // import 'core-js/es6/function'; // import 'core-js/es6/parse-int'; // import 'core-js/es6/parse-float'; // import 'core-js/es6/number'; // import 'core-js/es6/math'; // import 'core-js/es6/string'; // import 'core-js/es6/date'; // import 'core-js/es6/array'; // import 'core-js/es6/regexp'; // import 'core-js/es6/map'; // import 'core-js/es6/set'; /** IE10 and IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** IE10 and IE11 requires the following to support `@angular/animation`. */ // import 'web-animations-js'; // Run `npm install --save web-animations-js`. /** Evergreen browsers require these. **/ import 'core-js/es6/reflect'; import 'core-js/es7/reflect'; /** ALL Firefox browsers require the following to support `@angular/animation`. **/ // import 'web-animations-js'; // Run `npm install --save web-animations-js`. /*************************************************************************************************** * Zone JS is required by Angular itself. */ import 'zone.js/dist/zone'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS */ /** * Date, currency, decimal and percent pipes. * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 */ // import 'intl'; // Run `npm install --save intl`. ================================================ FILE: examples/angular/src/styles.css ================================================ /* You can add global styles to this file, and also import other style files */ ================================================ FILE: examples/angular/src/test.ts ================================================ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js/dist/long-stack-trace-zone'; import 'zone.js/dist/proxy.js'; import 'zone.js/dist/sync-test'; import 'zone.js/dist/jasmine-patch'; import 'zone.js/dist/async-test'; import 'zone.js/dist/fake-async-test'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. declare var __karma__: any; declare var require: any; // Prevent Karma from running prematurely. __karma__.loaded = function () {}; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting() ); // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); // And load the modules. context.keys().map(context); // Finally, start Karma to run the tests. __karma__.start(); ================================================ FILE: examples/angular/src/tsconfig.app.json ================================================ { "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/app", "module": "es2015", "baseUrl": "", "types": [] }, "exclude": [ "test.ts", "**/*.spec.ts" ] } ================================================ FILE: examples/angular/src/tsconfig.spec.json ================================================ { "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/spec", "module": "commonjs", "target": "es5", "baseUrl": "", "types": [ "jasmine", "node" ] }, "files": [ "test.ts" ], "include": [ "**/*.spec.ts", "**/*.d.ts" ] } ================================================ FILE: examples/angular/src/typings.d.ts ================================================ /* SystemJS module definition */ declare var module: NodeModule; interface NodeModule { id: string; } ================================================ FILE: examples/angular/tsconfig.json ================================================ { "compileOnSave": false, "compilerOptions": { "outDir": "./dist/out-tsc", "baseUrl": "src", "sourceMap": true, "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es5", "typeRoots": [ "node_modules/@types" ], "lib": [ "es2016", "dom" ] } } ================================================ FILE: examples/angular/tslint.json ================================================ { "rulesDirectory": [ "node_modules/codelyzer" ], "rules": { "callable-types": true, "class-name": true, "comment-format": [ true, "check-space" ], "curly": true, "eofline": true, "forin": true, "import-blacklist": [true, "rxjs"], "import-spacing": true, "indent": [ true, "spaces" ], "interface-over-type-literal": true, "label-position": true, "max-line-length": [ true, 140 ], "member-access": false, "member-ordering": [ true, "static-before-instance", "variables-before-functions" ], "no-arg": true, "no-bitwise": true, "no-console": [ true, "debug", "info", "time", "timeEnd", "trace" ], "no-construct": true, "no-debugger": true, "no-duplicate-variable": true, "no-empty": false, "no-empty-interface": true, "no-eval": true, "no-inferrable-types": [true, "ignore-params"], "no-shadowed-variable": true, "no-string-literal": false, "no-string-throw": true, "no-switch-case-fall-through": true, "no-trailing-whitespace": true, "no-unused-expression": true, "no-use-before-declare": true, "no-var-keyword": true, "object-literal-sort-keys": false, "one-line": [ true, "check-open-brace", "check-catch", "check-else", "check-whitespace" ], "prefer-const": true, "quotemark": [ true, "single" ], "radix": true, "semicolon": [ "always" ], "triple-equals": [ true, "allow-null-check" ], "typedef-whitespace": [ true, { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" } ], "typeof-compare": true, "unified-signatures": true, "variable-name": false, "whitespace": [ true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type" ], "directive-selector": [true, "attribute", "app", "camelCase"], "component-selector": [true, "element", "app", "kebab-case"], "use-input-property-decorator": true, "use-output-property-decorator": true, "use-host-property-decorator": true, "no-input-rename": true, "no-output-rename": true, "use-life-cycle-interface": true, "use-pipe-transform-interface": true, "component-class-suffix": true, "directive-class-suffix": true, "no-access-missing-member": true, "templates-use-public": true, "invoke-injectable": true } } ================================================ FILE: examples/axe.html ================================================ Testing AXE

================================================ FILE: examples/basic/chat.html ================================================
    ================================================ FILE: examples/basic/emoji.html ================================================

    Moved to ./chat.html!

    ================================================ FILE: examples/basic/meet.html ================================================
    must press play or unmute on new videos to accept meeting
    Stream
    ================================================ FILE: examples/basic/note.html ================================================ ================================================ FILE: examples/basic/paste.html ================================================

    Moved to ./note.html!

    ================================================ FILE: examples/basic/poll.html ================================================
    add new title, text, question...
    ================================================ FILE: examples/basic/post.html ================================================

    Posts

      ================================================ FILE: examples/basic/private.html ================================================

      Login

      Profile

      Data is privately encrypted by default. "+" to grant access, "x" to revoke access.





      Public Key:
      ================================================ FILE: examples/basic/schedule.html ================================================

      Schedule

      :
      • 0
      • ================================================ FILE: examples/basic/screen.html ================================================
        ================================================ FILE: examples/basic/stream.html ================================================

        Stream add resolution or
        ================================================ FILE: examples/basic/tables.html ================================================

        Tables


          ================================================ FILE: examples/basic/upload.html ================================================

          Drag & drop videos, songs, or images!

          ================================================ FILE: examples/basic/user.html ================================================

          Moved to ./post.html!

          ================================================ FILE: examples/basic/video.html ================================================
          Record or
          ================================================ FILE: examples/chat/index.html ================================================ Converse

          Have a Conversation...

        • 0
        • ================================================ FILE: examples/chat/user.html ================================================ ================================================ FILE: examples/contact/index.html ================================================
          Welcome,
          Enter your public username.
          And a long private passphrase.
          or
          more info

            Here is a list of people:

        • Alias:
        • Name

          bio

          A mysterious new example app has appeared! It is not finished/ready yet.

          Hello world!

          ================================================ FILE: examples/docs.html ================================================ Docs
          ================================================ FILE: examples/express.js ================================================ console.log("If module not found, install express globally `npm i express -g`!"); var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 8765; var express = require('express'); var Gun = require('..'); require('../axe'); var app = express(); app.use(Gun.serve); app.use(express.static(__dirname)); var server = app.listen(port); var gun = Gun({ file: 'data', web: server }); global.Gun = Gun; /// make global to `node --inspect` - debug only global.gun = gun; /// make global to `node --inspect` - debug only console.log('Server started on port ' + port + ' with /gun'); ================================================ FILE: examples/game/furball.html ================================================ Furball

          Neon ERA presents

          Furball Forces

          Choose Team:

          Episode 1: Waking

          "How long until they're online?"

          "We're copying the soul files, almost done."

          "Monsters are on the bridge, we do not have time!"

          "The new body is printing now, it'll be able to outrun them all, just hold on."

          "It won't know where to run! We're risking ruining the whole resistance, I need to talk to it now."

          "95% done." The voice behind the glass turns to the soul in the body, "My cub, can you hear me?"

          ...

          SCORE: 0%
          LIFE: 50%

          A fire explodes in the room behind the glass as an AutoMecha blows the door open.

          The floor shakes and the bed crashes through the wall, flying out of the building.

          "Mom!!!"

          There is a total free fall from 10 levels up, water down below.

          ...

          The water splashes, swelling and swirling all around.

          ...

          Rapidly tap to swim up to air:

          Episode 2: Who Am I?

          "Grab on!" A voice calls out from the darkness.

          A life vest hits the water and floats within arm's distance.

          The shivering body is pulled up onto the boat.

          "Wow, you're heavier than you look. Are you OK? What's your name?"

          ...

          Write your reply & hit enter:

          "Well, it's a miracle you did not die in the building explosion or from that fall."

          "What is going on? What happened?"

          "You can't remember? Your brain must be knocked up pretty hard."

          "No, I was mid copy into this body and now my memories are glitching."

          "Woah, you're one of those pro elite AREION revolutionaries? All flesh & blood! Dense, too. I would've assumed they were stealing AutoMecha tech for that instead."

          "I was about to be told vital data for the resistance, but then they blew up the build--"

          ...

          "Hey, what's the matter?"

          "My mom. She was in there. I need to go back. Please, help me and tell me everything you know."

          "I'm so sorry. I can only get so close with the boat, you're gonna have to jump over a lot of broken bits. You ready?"

          ...

          ... to be continued ...

          Episode 1: Training

          ...

          For You,

          Crafted with love, by ERA.

          ================================================ FILE: examples/game/nts.html ================================================

          ================================================ FILE: examples/game/space.html ================================================

          ================================================ FILE: examples/game/win.html ================================================ Win

          how to

          Win at Life!

          success, fame, power.

          sex, ethics, & integrity.

          Step 1: Breathe

          Step 2: Drink Water

          Step 3: Eat Once a Day

          If you do not want to be eaten, do not eat things that would not want to be eaten.

          Step 4: Babymaking* 😉

          Find a willing player.

          * This does not always make babies.

          Step 5: Make Dance

          Moving your body is how you express your thoughts.

          What you do with your body is what others will come to know you for. So do well.

          You can make art, songs, or stories; You can make science, tools, or discoveries.

          Who are you?

          Science: Knowing Games

          If you must win one game, it should be the game of making games.

          If you can make any game, then you will know how to win any game.

          Games have goals and play.

          Play is a safe space to try new dances.

          Goals try to get players to do a type of dance.

          The simplest goal is to not "die" in the game.

          Oh look, you've fallen into water and cannot breathe.

          If you do not push the button to swim to the top, you'll lose the game.

          SCORE: 0%
          LIFE: 100%

          You won your first game! 🎉

          See? I told you breathing is important.

          You also learned the most basic dance: rapid poking.

          The goal of the next game is to make the game you just won.

          Bend these Rules if it is more Moral to do so

          GAME OVER

          ================================================ FILE: examples/hapi.js ================================================ console.log("If module not found, install hapi globally `npm i hapi inert -g`!") const Hapi = require('hapi') const Inert = require('inert') const Gun = require('..') const server = new Hapi.Server({ port: 8765, host: 'localhost', routes: { files: { relativeTo: require('path').join(__dirname, '..') } } }) async function runtime() { const db = new Gun({ web: server.listener, file: 'data.json' }) await server.register(Inert) server.route({ method: 'GET', path: '/gun.js', handler: { file: 'gun.min.js' } }) server.route({ method: 'GET', path: '/gun/nts.js', handler: { file: 'nts.js' } }) server.route({ method: 'GET', path: '/{param*}', handler: { directory: { path: __dirname, redirectToSlash: true, index: true } } }) await server.start() console.log('Server running at:', server.info.uri) } runtime() ================================================ FILE: examples/http.js ================================================ ;(function(){ var cluster = require('cluster'); if(cluster.isMaster){ return cluster.fork() && cluster.on('exit',function(){ cluster.fork(); require('../lib/crashed') }); } var fs = require('fs'), env = process.env; var GUN = require('../'); // require('gun'); var opt = { port: env.PORT || process.argv[2] || 8765, peers: env.PEERS && env.PEERS.split(',') || [] }; if(fs.existsSync((opt.home = require('os').homedir())+'/cert.pem')){ env.HTTPS_KEY = env.HTTPS_KEY || opt.home+'/key.pem'; env.HTTPS_CERT = env.HTTPS_CERT || opt.home+'/cert.pem'; } if(env.HTTPS_KEY){ opt.port = 443; opt.key = fs.readFileSync(env.HTTPS_KEY); opt.cert = fs.readFileSync(env.HTTPS_CERT); opt.server = require('https').createServer(opt, GUN.serve(__dirname)); require('http').createServer(function(req, res){ res.writeHead(301, {"Location": "https://"+req.headers['host']+req.url }); res.end(); }).listen(80); } else { opt.server = require('http').createServer(GUN.serve(__dirname)); } var gun = GUN({web: opt.server.listen(opt.port), peers: opt.peers}); console.log('Relay peer started on port ' + opt.port + ' with /gun'); module.exports = gun; }()); ================================================ FILE: examples/https.sh ================================================ #!/bin/bash cd ~ git clone https://github.com/acmesh-official/acme.sh.git cd ~/acme.sh ./acme.sh --install -m $EMAIL bash ~/acme.sh/acme.sh --issue -d $DOMAIN -w $WEB bash ~/acme.sh/acme.sh --install-cert -d $DOMAIN --key-file ~/key.pem --fullchain-file ~/cert.pem --reloadcmd "service relay force-reload" ================================================ FILE: examples/index.html ================================================

          This is the examples folder.

          The most basic example is ./basic/note.html!

          Home page temporarily disabled.

          ================================================ FILE: examples/infinite-scroll/ScrollWindow.js ================================================ const DEFAULT_OPTIONS = { size: 20, stickTo: 'top', }; class ScrollWindow { constructor(gunNode, opts = {}) { this.opts = Object.assign(DEFAULT_OPTIONS, opts); this.elements = new Map(); this.node = gunNode; this.center = this.opts.startAt; this.updateSubscriptions(); } updateSubscriptions() { this.upSubscription && this.upSubscription.off(); this.downSubscription && this.downSubscription.off(); const subscribe = params => { this.node.get({ '.': params}).map().on((val, key, a, eve) => { if (params['-']) { this.downSubscription = eve; } else { this.upSubscription = eve; } this._addElement(key, val); }); }; if (this.center) { subscribe({ '>': this.center, '<': '\uffff' }); subscribe({'<': this.center, '>' : '', '-': true}); } else { subscribe({ '<': '\uffff', '>': '', '-': this.opts.stickTo === 'top' }); } } _getSortedKeys() { this.sortedKeys = this.sortedKeys || [...this.elements.keys()].sort(); return this.sortedKeys; } _upOrDown(n, up) { this.opts.stickTo = null; const keys = this._getSortedKeys(); n = n || (keys.length / 2); n = up ? n : -n; const half = Math.floor(keys.length / 2); const newMiddleIndex = Math.max(Math.min(half + n, keys.length - 1), 0); if (this.center !== keys[newMiddleIndex]) { this.center = keys[newMiddleIndex]; this.updateSubscriptions(); } return this.center; } up(n) { return this._upOrDown(n, true); } down(n) { return this._upOrDown(n, false); } _topOrBottom(top) { this.opts.stickTo = top ? 'top' : 'bottom'; this.center = null; this.updateSubscriptions(); } top() { this._topOrBottom(true); } bottom() { this._topOrBottom(false); } _addElement(key, val) { if (!val || this.elements.has(key)) return; const add = () => { this.elements.set(key, val); this.sortedKeys = [...this.elements.keys()].sort(); const sortedElements = this.sortedKeys.map(k => this.elements.get(k)); this.opts.onChange && this.opts.onChange(sortedElements); }; const keys = this._getSortedKeys(); if (keys.length < this.opts.size) { add(); } else { if (this.opts.stickTo === 'top' && key > keys[0]) { this.elements.delete(keys[0]); add(); } else if (this.opts.stickTo === 'bottom' && key < keys[keys.length - 1]) { this.elements.delete(keys[keys.length - 1]); add(); } else if (this.center) { if (keys.indexOf(this.center) < (keys.length / 2)) { if (key < keys[keys.length - 1]) { this.elements.delete(keys[keys.length - 1]); add(); } } else { if (key > keys[0]) { delete this.elements.delete(keys[0]); add(); } } } } } getElements() { return this.elements; } } ================================================ FILE: examples/infinite-scroll/index.html ================================================ Infinite scroll example
          ================================================ FILE: examples/infinite-scroll/index.js ================================================ const gun = new Gun(); const size = 20; const gunNode = gun.get('posts'); function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; let topSentinelPreviousY = 0; let topSentinelPreviousRatio = 0; let bottomSentinelPreviousY = 0; let bottomSentinelPreviousRatio = 0; let previousUpIndex = previousDownIndex = -1; const render = elements => { const t = new Date(); elements.reverse().forEach((data, j) => { var date = new Date(data.date); $('#date' + j).text(date.toLocaleDateString() + ' ' + date.toLocaleTimeString()); $('#text' + j).text(data.text); $('#img' + j).attr('src', ''); $('#img' + j).attr('src', _getCatImg(date.getTime())); $('#post' + j).css({visibility: 'visible'}); }); console.log('rendering took', new Date().getTime() - t.getTime(), 'ms'); window.onRender && window.onRender(elements); }; const onChange = debounce(render, 20); const scroller = new ScrollWindow(gunNode, {size, stickTo: 'top', onChange}); const initList = () => { for (var n = 0; n < size; n++) { var el = $("
          ").addClass('post').attr('id', 'post' + n).css({visibility: 'hidden'}); el.append($('').attr('id', 'date' + n)); el.append($('').attr('id', 'text' + n)); el.append($('').attr('id', 'img' + n).attr('height', 100).attr('width', 100)); $('#container').append(el); } } const _getCatImg = (n) => { const url = "https://source.unsplash.com/collection/139386/100x100/?sig="; return url + n % 999999; }; const getNumFromStyle = numStr => Number(numStr.substring(0, numStr.length - 2)); const adjustPaddings = isScrollDown => { const container = document.getElementById("container"); const currentPaddingTop = getNumFromStyle(container.style.paddingTop); const currentPaddingBottom = getNumFromStyle(container.style.paddingBottom); const remPaddingsVal = 198 * (size / 2); // TODO: calculate actual element heights if (isScrollDown) { container.style.paddingTop = currentPaddingTop + remPaddingsVal + "px"; container.style.paddingBottom = currentPaddingBottom === 0 ? "0px" : currentPaddingBottom - remPaddingsVal + "px"; } else { container.style.paddingBottom = currentPaddingBottom + remPaddingsVal + "px"; if (currentPaddingTop === 0) { $(window).scrollTop($('#post0').offset().top + remPaddingsVal); } else { container.style.paddingTop = currentPaddingTop - remPaddingsVal + "px"; } } } const topSentCallback = entry => { const container = document.getElementById("container"); const currentY = entry.boundingClientRect.top; const currentRatio = entry.intersectionRatio; const isIntersecting = entry.isIntersecting; // conditional check for Scrolling up if ( currentY > topSentinelPreviousY && isIntersecting && currentRatio >= topSentinelPreviousRatio && scroller.center !== previousUpIndex && // stop if no new results were received scroller.opts.stickTo !== 'top' ) { previousUpIndex = scroller.center; adjustPaddings(false); scroller.up(size / 2); } topSentinelPreviousY = currentY; topSentinelPreviousRatio = currentRatio; } const botSentCallback = entry => { const currentY = entry.boundingClientRect.top; const currentRatio = entry.intersectionRatio; const isIntersecting = entry.isIntersecting; // conditional check for Scrolling down if ( currentY < bottomSentinelPreviousY && currentRatio > bottomSentinelPreviousRatio && isIntersecting && scroller.center !== previousDownIndex && // stop if no new results were received scroller.opts.stickTo !== 'bottom' ) { previousDownIndex = scroller.center; adjustPaddings(true); scroller.down(size / 2); } bottomSentinelPreviousY = currentY; bottomSentinelPreviousRatio = currentRatio; } const initIntersectionObserver = () => { const options = { //rootMargin: '190px', } const callback = entries => { entries.forEach(entry => { if (entry.target.id === 'post0') { topSentCallback(entry); } else if (entry.target.id === `post${size - 1}`) { botSentCallback(entry); } }); } var observer = new IntersectionObserver(callback, options); // TODO: It's possible to quickly scroll past the sentinels without them firing. Top and bottom sentinels should extend to page top & bottom? observer.observe(document.querySelector("#post0")); observer.observe(document.querySelector(`#post${size - 1}`)); } initList(size); initIntersectionObserver(); $('#top').click(() => { scroller.top(); $('#container').css({'padding-top': 0, 'padding-bottom': 0}); $(document.body).animate({ scrollTop: 0 }, 500); }); $('#bottom').click(() => { scroller.bottom(); $('#container').css({'padding-top': 0, 'padding-bottom': 0}); $(document.body).animate({ scrollTop: $("#container").height() }, 500); }); $('#generate').submit(e => { e.preventDefault(); const day = 24 * 60 * 60 * 1000; const year = 365 * day; const n = Number($('#number').val()); for (let i = 0; i < n; i++) { const d = new Date(40 * year + i * day).toISOString(); gunNode.get(d).put({text: 'Hello world!', date: d}); } }); ================================================ FILE: examples/infinite-scroll/style.css ================================================ html, body { margin: 0; padding: 0; } body { padding-top: 65px; } header { background: rgba(255,255,255,0.75); padding: 15px; } header { position: fixed; top: 0; left: 0; right: 0; } #bottom { position: fixed; right: 15px; bottom: 15px; } input { border: 0; background-color: #efefef; padding: 15px; border-radius: 50px; } button { background-color: #4a4f9d; border: 0; padding: 15px; color: white; border-radius: 50px; } input, button { outline: none; opacity: 1; } input:focus, button:focus, button:hover { opacity: 0.8; } button:hover { cursor: pointer; } #top-buttons, form { display: inline-block; margin: 0; } #top-buttons { float: right; } .post { margin: 15px; padding: 15px; background-color: #9de1fe; border-radius: 5px; } .post b { margin-right: 5; } .post img { display: block; margin: 10px 0; } ================================================ FILE: examples/install.sh ================================================ #!/bin/bash # README # This will install nodejs and npm on your system, # should work on most places other than Windows. # For it to run on boot as a server, a recent OS is needed. # Set any environment variables before you run this, # like `export RAD=false` to disable storage, or # pass file paths of `HTTPS_CERT` & `HTTPS_KEY`, etc. # Copy paste and run each line into your terminal. # If you are on Windows, http://nodejs.org/download/ has # an installer that will automatically do it for you. # curl -o- https://raw.githubusercontent.com/amark/gun/master/examples/install.sh | bash # wget -O - https://raw.githubusercontent.com/amark/gun/master/examples/install.sh | bash #debian/ubuntu cd ~ apt-get install sudo -y sudo apt-get update -y sudo apt-get install curl git git-core systemd -y sudo apt-get install systemctl -y #fedora/openSUSE sudo yum check-update -y sudo yum install curl git git-core systemd -y sudo yum install systemctl -y #screen -S install # You can safely CTRL+A+D to escape without stopping the process. `screen -R install` to resume. Stop all with `killall screen`. Note: May need to `sudo apt-get install screen` # install nodejs git clone https://github.com/isaacs/nave.git ./nave/nave.sh usemain stable # If you just want nodejs and npm but not gun, stop here. #npm install gun@latest #cd ./node_modules/gun mkdir node_modules git clone https://github.com/amark/gun.git cd gun git checkout . git pull git checkout master git checkout $VERSION git pull npm install . cp ./examples/relay.service /lib/systemd/system/relay.service echo $PWD >> /lib/systemd/system/relay.service echo "fs.file-max = 999999" >> /etc/sysctl.conf ulimit -u unlimited sysctl -p /etc/sysctl.conf systemctl daemon-reload systemctl enable relay systemctl restart relay ================================================ FILE: examples/jquery.js ================================================ /*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */ !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; }return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML="
          a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
          ","
          "],area:[1,"",""],param:[1,"",""],thead:[1,"","
          "],tr:[2,"","
          "],col:[2,"","
          "],td:[3,"","
          "],_default:l.htmlSerialize?[0,"",""]:[1,"X
          ","
          "]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("