{"_id":"5635b294d209b50d0031dfe6","__v":0,"user":"5469e5dfa3b67a0e00559b06","project":"550a7754635c660d0052808e","githubsync":"","category":{"_id":"5635b291d209b50d0031dfc7","pages":["5635b294d209b50d0031dfdf","5635b294d209b50d0031dfe0","5635b294d209b50d0031dfe1","5635b294d209b50d0031dfe2","5635b294d209b50d0031dfe3","5635b294d209b50d0031dfe4","5635b294d209b50d0031dfe5","5635b294d209b50d0031dfe6","5635b294d209b50d0031dfe7","5635b294d209b50d0031dfe8","5635b294d209b50d0031dfe9","5635b294d209b50d0031dfea","5635b294d209b50d0031dfeb","5635b294d209b50d0031dfec"],"project":"550a7754635c660d0052808e","__v":1,"version":"5635b290d209b50d0031dfc4","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-04-09T03:24:43.474Z","from_sync":false,"order":2,"slug":"customizing-telescope","title":"Customizing Telescope"},"version":{"_id":"5635b290d209b50d0031dfc4","__v":1,"project":"550a7754635c660d0052808e","createdAt":"2015-11-01T06:34:56.868Z","releaseDate":"2015-11-01T06:34:56.868Z","categories":["5635b291d209b50d0031dfc5","5635b291d209b50d0031dfc6","5635b291d209b50d0031dfc7","5635b291d209b50d0031dfc8","5635b291d209b50d0031dfc9","5635b291d209b50d0031dfca"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"0.25.0","version":"0.25"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2015-05-10T02:26:04.506Z","link_external":false,"link_url":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":22,"body":"Telescope exposes a callback system that lets you hook into operations such as inserting a new comment or editing a post to add extra features. \n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Understanding Hooks & Callbacks\"\n}\n[/block]\nA **hook** is a specific point in the code where you can add a **callback**, in other words a special function that will be called when the hook is executed. \n\nYou can have as many callbacks as you want per hook, and they all work along a similar principle: they take an **object** as argument, modify it, and then return the updated object to be passed on to the next callback. \n\nAdditionally, callbacks can also take a second optional argument that *won't* be modified. This **constant** will also be passed to each callback function successively. \n\nFinally, Telescope handles two types of callback hooks: **synchronous hooks** (available on both the **client** and **server** pause the execution of the code until all callbacks have run. For example, you'd typically want to run any post submission validation callbacks synchronously, because you want the post submission to be on hold until all checks have passed. \n\nOn the other hand, **asynchonous hooks** (available only on the **server**) do *not* pause your code. A great example would be sending an email notification on post submission: this can be a long process (especially if you make a remote call to a third-party email service), so it's best to proceed with any next steps without waiting. \n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Adding a Hook\"\n}\n[/block]\nYou can add a hook with the `Telescope.callbacks.add` method. It takes two arguments, the **name** of the hook you're adding to, and the **callback function** to run. \n\nFor example, here's how the `telescope-embedly` package refreshes a post's `media` property whenever its URL is modified:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"function updateMediaOnEdit (modifier, post) {\\n  var newUrl = modifier.$set.url;\\n  if(newUrl && newUrl !== post.url){\\n    var data = getEmbedlyData(newUrl);\\n    if(!!data && !!data.media.html) {\\n      modifier.$set.media = data.media;\\n    }\\n  }\\n  return modifier;\\n}\\nTelescope.callbacks.add(\\\"postEdit\\\", updateMediaOnEdit);\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Named Functions\",\n  \"body\": \"By using named functions (`function foo () {}`) instead of the usual anonymous function syntax (`var foo = function () {}`), you can expose the `function.name` variable, which can be useful when debugging callback issues.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Removing a Hook\"\n}\n[/block]\nYou can remove a hook with `Telescope.callbacks.remove(hookName, callbackName)`.\n\nNote that this only works if the callback you want to remove *has* a name (see “Named Functions” above).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Running Hooks\"\n}\n[/block]\nWhile most people will probably not need to implement new callback hooks, it can still be done easily with `Telescope.callbacks.run()` and `Telescope.callbacks.runAsync()`. \n\n`Telescope.callbacks.run()` takes three arguments:\n\n- `hook`: the name of the hook (if the hook doesn't exist yet, it'll automatically be created).\n- `item`: the item to iterate on (which will be modified and passed on to each iteration).\n- `constant`: (optional) an object that will be passed to each iteration unchanged.\n\nWhile `Telescope.callbacks.runAsync()` takes two:\n\n- `hook`: the name of the hook.\n- `constant`: the object that will be passed to each iteration.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Callbacks Hooks\"\n}\n[/block]\nHere's a list of all available callback hooks, along with a description and the contents of the **item** (and optionally **constant**) arguments passed to their callbacks.\n\n**Posts Hooks**\n\n- `postSubmitClient`: called before post insertion on the client (`post`).\n- `postSubmit`: called before post insertion on the server (`post`).\n- `postSubmitAsync`: called after post insertion on the server (`post`).\n- `postEditClient`: called before post update on the client (`modifier`, `post`).\n- `postEdit`: called before post update on the server (`modifier`, `post`).\n- `postEditAsync`: called after post update on the server (`newPost`, `oldPost`).\n- `postApprovedAsync`: called after post approval on the server (`post`).\n- `postClass`: used to add classes to `.post` divs (`postClass`). \n\n**Comments Hooks**\n\nSame as posts, but with comments. \n\n- `commentSubmitClient`\n- `commentSubmit`\n- `commentSubmitAsync`\n- `commentEditClient`\n- `commentEdit`\n- `commentEditAsync`\n\n**Vote Hooks**\n\nAll of the following hooks' callback functions run on an `item` object, which can be either a post or comment.\n\n- `upvote`\n- `upvoteAsync`\n- `downvote`\n- `downvoteAsync`\n- `cancelUpvote`\n- `cancelUpvoteAsync`\n- `cancelDownvote`\n- `cancelDownvoteAsync`\n\n**User Hooks**\n\n- `onCreateUser`: called when a user creates their account (`user`).\n- `onCreateUserAsync`: same, but asynchronous (won't interrupt user creation) (`user`).\n- `profileCompletedChecks`: parse a user object to see if their profile is complete (`user`).\n- `profileCompletedAsync`: called either when a user object is first created (if their profile is complete), or else when a user first completes their profile (`user`).","excerpt":"","slug":"callback-hooks","type":"basic","title":"Callback Hooks"}
Telescope exposes a callback system that lets you hook into operations such as inserting a new comment or editing a post to add extra features. [block:api-header] { "type": "basic", "title": "Understanding Hooks & Callbacks" } [/block] A **hook** is a specific point in the code where you can add a **callback**, in other words a special function that will be called when the hook is executed. You can have as many callbacks as you want per hook, and they all work along a similar principle: they take an **object** as argument, modify it, and then return the updated object to be passed on to the next callback. Additionally, callbacks can also take a second optional argument that *won't* be modified. This **constant** will also be passed to each callback function successively. Finally, Telescope handles two types of callback hooks: **synchronous hooks** (available on both the **client** and **server** pause the execution of the code until all callbacks have run. For example, you'd typically want to run any post submission validation callbacks synchronously, because you want the post submission to be on hold until all checks have passed. On the other hand, **asynchonous hooks** (available only on the **server**) do *not* pause your code. A great example would be sending an email notification on post submission: this can be a long process (especially if you make a remote call to a third-party email service), so it's best to proceed with any next steps without waiting. [block:api-header] { "type": "basic", "title": "Adding a Hook" } [/block] You can add a hook with the `Telescope.callbacks.add` method. It takes two arguments, the **name** of the hook you're adding to, and the **callback function** to run. For example, here's how the `telescope-embedly` package refreshes a post's `media` property whenever its URL is modified: [block:code] { "codes": [ { "code": "function updateMediaOnEdit (modifier, post) {\n var newUrl = modifier.$set.url;\n if(newUrl && newUrl !== post.url){\n var data = getEmbedlyData(newUrl);\n if(!!data && !!data.media.html) {\n modifier.$set.media = data.media;\n }\n }\n return modifier;\n}\nTelescope.callbacks.add(\"postEdit\", updateMediaOnEdit);", "language": "javascript" } ] } [/block] [block:callout] { "type": "info", "title": "Named Functions", "body": "By using named functions (`function foo () {}`) instead of the usual anonymous function syntax (`var foo = function () {}`), you can expose the `function.name` variable, which can be useful when debugging callback issues." } [/block] [block:api-header] { "type": "basic", "title": "Removing a Hook" } [/block] You can remove a hook with `Telescope.callbacks.remove(hookName, callbackName)`. Note that this only works if the callback you want to remove *has* a name (see “Named Functions” above). [block:api-header] { "type": "basic", "title": "Running Hooks" } [/block] While most people will probably not need to implement new callback hooks, it can still be done easily with `Telescope.callbacks.run()` and `Telescope.callbacks.runAsync()`. `Telescope.callbacks.run()` takes three arguments: - `hook`: the name of the hook (if the hook doesn't exist yet, it'll automatically be created). - `item`: the item to iterate on (which will be modified and passed on to each iteration). - `constant`: (optional) an object that will be passed to each iteration unchanged. While `Telescope.callbacks.runAsync()` takes two: - `hook`: the name of the hook. - `constant`: the object that will be passed to each iteration. [block:api-header] { "type": "basic", "title": "Callbacks Hooks" } [/block] Here's a list of all available callback hooks, along with a description and the contents of the **item** (and optionally **constant**) arguments passed to their callbacks. **Posts Hooks** - `postSubmitClient`: called before post insertion on the client (`post`). - `postSubmit`: called before post insertion on the server (`post`). - `postSubmitAsync`: called after post insertion on the server (`post`). - `postEditClient`: called before post update on the client (`modifier`, `post`). - `postEdit`: called before post update on the server (`modifier`, `post`). - `postEditAsync`: called after post update on the server (`newPost`, `oldPost`). - `postApprovedAsync`: called after post approval on the server (`post`). - `postClass`: used to add classes to `.post` divs (`postClass`). **Comments Hooks** Same as posts, but with comments. - `commentSubmitClient` - `commentSubmit` - `commentSubmitAsync` - `commentEditClient` - `commentEdit` - `commentEditAsync` **Vote Hooks** All of the following hooks' callback functions run on an `item` object, which can be either a post or comment. - `upvote` - `upvoteAsync` - `downvote` - `downvoteAsync` - `cancelUpvote` - `cancelUpvoteAsync` - `cancelDownvote` - `cancelDownvoteAsync` **User Hooks** - `onCreateUser`: called when a user creates their account (`user`). - `onCreateUserAsync`: same, but asynchronous (won't interrupt user creation) (`user`). - `profileCompletedChecks`: parse a user object to see if their profile is complete (`user`). - `profileCompletedAsync`: called either when a user object is first created (if their profile is complete), or else when a user first completes their profile (`user`).