{"id":20206995,"url":"https://github.com/tomgp/ft-workshop-ex4","last_synced_at":"2026-05-05T16:33:13.834Z","repository":{"id":142289596,"uuid":"45906393","full_name":"tomgp/FT-workshop-EX4","owner":"tomgp","description":"MV* and event dispatching excercise","archived":false,"fork":false,"pushed_at":"2015-11-26T16:53:59.000Z","size":114,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-13T20:49:46.793Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomgp.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-11-10T11:02:38.000Z","updated_at":"2015-11-10T13:23:37.000Z","dependencies_parsed_at":"2023-03-13T20:23:00.699Z","dependency_job_id":null,"html_url":"https://github.com/tomgp/FT-workshop-EX4","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomgp%2FFT-workshop-EX4","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomgp%2FFT-workshop-EX4/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomgp%2FFT-workshop-EX4/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomgp%2FFT-workshop-EX4/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomgp","download_url":"https://codeload.github.com/tomgp/FT-workshop-EX4/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241644543,"owners_count":19996177,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T05:27:04.376Z","updated_at":"2026-05-05T16:33:08.811Z","avatar_url":"https://github.com/tomgp.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"##EX 4 - code structure for interactive graphics\n\nSo far we've only really considered graphics that takesome data and get redrered once -- in terms of user input the most complext case we've looked at is resizing the browser window. Accepting user input which then changes the data which in turn changes the visualisation of that data is a great opportunity to get your code tied up in all sorts of knots.\n\nBefore we look at some specific techniques it's worth quickly looking back at some of the good habits we've seen in the earlier excercises\n\n * __Make funtions without side effects__: There are techy CS reasons for this but in practical terms it makes them easier to consider as black boxes, letting you think of them as an abstraction rather and a set of implementation details. It makes it easier to think about you program as a whole. \n\n * __Separate concerns__: The process ▶️ 1. get the data ➡️ 2. process the data ➡️ 3. draw the data. If you treat each of these steps as separate considering the inputs and outputs you expect from each stage, that's a good start to producing modular code.\n\n * __Use ```call``` for complex bits for the vis__: for putting multiple children on a parent selection then call is indispensable, it'll also make it easier to abstract and resuse complex bits of code with almost not extra effort up front. \n\n##Make some inputs and outputs\nin this case we have 3 inputs and 3 outputs (each input looks like an output but it's useful to separate them conceptually)\n \n![bbc example](bbc-example.png)\n\nHow do we keep all those things in sync without overwhelming amounts of code, repetetive code etc.\n\n##Make a model\n\nWhat we want here is a single source of __THE TRUTH__ something that represents the state of the application and its data ( this might be two things or one thing with two bits but the fact is its easy to change data and state  without haveing to worry about the whole app getting he message ).\n\nA simple model for the above might look like this:\n\n```\nvar model = {\n\tx:100,\n\ty:100\n};\n```\n\nbut when you change a property on the model you need to let everything know how do you do that?\n\n##Make an event dispatcher\n\nThere are plenty of libraries which provide Javascript with a mechanism to easily dispatch custom events. We'll use D3 as for visualisations you'll probably have that on the page anyway.\n\nHere's and example of an event dispatcher in D3\n\n```\nvar dispatcher = d3.dispatch('myEvent');\n\ndispatcher.on('myEvent', function(){\n\tconsole.log('my event happened');\n});\n\n//trigger the event like this\ndispatcher.myEvent();\n```\nnote if you want more than one thing to happen on a given event you need to differentiate in the handler by giving a unique sting follwing a `.` (slightly annoying)\ne.g.\n\n```\ndispatcher.on('myEvent.a', function(){ \n//do one thing });\n\ndispatcher.on('myEvent.b', function(){ \n//do another thing });\n```\n\n###Provide an 'official' way to modify the model\n\nThe model should have an event dispatcher as a property so it can signal to the outside world when it changes but in order to actually trigger that signal we need the model to notice whe it has changed. THe easiest way to do this is by providing it with a set method via which the rest of the app must adjust its properties\nsomrthing like\n\n```\nfunction X(x){\n\tif(!x) return model.x;\n\tmodel.x = x;\n\tdispatcher.change(model);\n}\n```\n\nnote: the dispacher's function call passes the `model` as an argument, this is an easy way to ensure any listener has access to its properties.\n\n####branch: make-an-event-dispatcher\n\n####branch: modularise\n\n####branch: refactor nicely\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomgp%2Fft-workshop-ex4","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomgp%2Fft-workshop-ex4","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomgp%2Fft-workshop-ex4/lists"}