photo-browser.mustache revision c3573884ddb87405d819f8c70cb7fed1ff8f471e
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<div class="intro">
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>This example uses DD and <a href="http://developer.yahoo.com/yql/">YQL</a> to build a Photo Browser application. This example was part of the YUI 3 presentation by <a href="http://twiiter.com/davglass">@davglass</a> at <a href="http://openhacklondon.pbworks.com/">Open Hack : London</a></p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<div class="example newwindow">
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff <a href="photo-browser-example.html" target="_blank" class="button">
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff View Example in New Window
58007c5fde59b756174280d26916eb27f593e6ccBob Halley<h3>Drag and Drop</h3>
58007c5fde59b756174280d26916eb27f593e6ccBob Halley<p>In this example, Drag and Drop is heavily customized by using `event bubbling` and `custom proxies`.</p>
58007c5fde59b756174280d26916eb27f593e6ccBob Halley<p>When you see `Y.DD.DDM.on` in the code, you are seeing the built-in `event bubbling`.</p>
58007c5fde59b756174280d26916eb27f593e6ccBob Halley<p>The DD `dragNode` is the proxy node, we add some styles to it allowing it to look the way we want.</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>Here is the Flickr YQL query used in this example.</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffSELECT * FROM flickr.photos.search(100) WHERE
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff (text="yuiconf")
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffAND (safe_search = 1)
a55d0a9080c8ef4117d2fc27f63220a56afb2434Andreas GustafssonAND (media = "photos")
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<h3>Slider and StyleSheet</h3>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>In this example, we will use the Slider control to dynamically manipulate a CSS Style Rule.</p>
58007c5fde59b756174280d26916eb27f593e6ccBob Halley<p>First, we need to create the slider and render it.</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff//Create and render the slider
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff length: '200px', value: 40, max: 70, min: 5
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff}).render('.horiz_slider');
353dcaf1cc77d122d9b4b750bbbfc4c96b4b292bAndreas Gustafsson<p>Now, we listen for the Slider's `valueChange` event. This event is fired when the value of the Slider has changed.</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>Next we use the StyleSheet utility to dynamically change a style rule to resize the images.
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffThe style rule that we want to change is `#yui-main .yui-g ul li`. When the Slider's value changes, we will take the value and divide it by 2, then use that as the percentage width of the li.
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffThis will give us the effect we want (resizing images) without touching all the images via the DOM.
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff//Listen for the change
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graffsl.after('valueChange',function (e) {
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Insert a dynamic stylesheet rule:
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff var sheet = new Y.StyleSheet('image_slider');
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff sheet.set('#yui-main .yui-g ul li', {
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff width: (e.newVal / 2) + '%'
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<h3>Event Delegation</h3>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>This listener listens for all `mouseup` events on the `document` and it will only fire when the target element matches the `*` selector (which should be all elements).</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>This way we can remove all the `selected` CSS classes from all the images in the browser when a `mouseup` occurs, only if the shift key was not pressed. We can then check to determine if the mouseup came from one of the images. If it has, add the selected class back to it.</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff//Listen for all mouseups on the document (selecting/deselecting images)
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffY.delegate('mouseup' , function(e) {
58007c5fde59b756174280d26916eb27f593e6ccBob Halley //No shift key - remove all selected images
58007c5fde59b756174280d26916eb27f593e6ccBob Halley wrapper.all('img.selected').removeClass('selected');
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Check if the target is an image and select it.
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff if (e.target.test('#yui-main .yui-g ul li img')) {
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff}, document, '*');
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>This listener, listens for all `click` events on the album list `#photoList li`.
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffFirst, it stops the click, so the href is not followed. Next, it removes all the `selected` classes from the list. Then, it adds the `selected` class to the item that was clicked on.</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>After that UI setup, it uses Selectors to change the view of the images in the browser.
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffFirst, it checks if we are viewing "all" or a "sub album". If all is selected, it removes the `hidden` class from all the images.
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffIf it was an album, it adds the `hidden` class to all the images, then selects all the images with the class of its `id`, then it removes the hidden class from them.
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>Basically, it hides all the images, then determines the ones it needs to show and removes the `hidden` class from them.</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff//Listen for all clicks on the '#photoList li' selector
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael GraffY.delegate('click', function(e) {
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Prevent the click
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Remove all the selected items
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff e.currentTarget.get('parentNode').all('li.selected').removeClass('selected');
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Add the selected class to the one that one clicked
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //The "All Photos" link was clicked
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Remove all the hidden classes
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff wrapper.all('li').removeClass('hidden');
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Another "album" was clicked, get its id
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Hide all items by adding the hidden class
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff wrapper.all('li').addClass('hidden');
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //Now, find all the items with the class name the same as the album id
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff //and remove the hidden class
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff wrapper.all('li.' + c).removeClass('hidden');
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff}, document, '#photoList li');
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<h3>Full Source</h3>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff<p>Here is the full commented JavaScript source for this example.</p>
5a0ffa97751ef1ff29d1bf9d7f332eeb9f8edc21Michael Graff{{> photo-browser-source-js}}